Merging two lists in a certain format in Python - python

I have two lists A and B. I am trying to merge the two lists into one in a specific format as shown in the expected output. I also show the current output.
A=[0, 1]
B=[[1,2],[3,4]]
C=A+B
print(C)
The current output is
[0, 1, [1, 2], [3, 4]]
The expected output is
[[0, 1, 2], [1, 3, 4]]

lst=[]
for x, y in zip(A, B):
lst.append([x] + y)
#[[0, 1, 2], [1, 3, 4]]
Or as #Mechanic Pig suggested in comments using list comprehension:
[[a] + b for a, b in zip(A, B)]

You can also use np.insert:
a = np.array([0, 1])
b = np.array([[1, 2], [3, 4]])
np.insert(b, 0, a, axis=1)

A=[0, 1]
B=[[1,2],[3,4]]
c=[]
for i in range(len(A)):
c.append([A[i]])
for j in range(len(B[i])):
c[i].append(B[i][j])
print(c)
[[0, 1, 2], [1, 3, 4]]

Related

How do I convert the rows of a matrix to columns in Python without NumPy?

I am working on a Sudoku Solver in Python, and I need to create functions in it. One of them checks the Sudoku Matrix and returns the number of rows in it that contains a repeating number.
def findRepeatsInColumn(matrix):
numRepeats = 0
for row in matrix:
safeChars=['[', ']', '/']
usedChars=[]
for char in str(row):
if char in usedChars and char not in safeChars:
numRepeats += 1
break
else:
usedChars.append(char)
return numRepeats
If I pass a matrix [[1, 1, 1], [2, 2, 2], [3, 3, 3]] to it, it functions fine and gives me the output 3, but for checking all columns for repeated numbers, I need to convert the rows into columns, which means I would need something like: Input: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
Output: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Any thoughts on how I could do this without NumPy?
One simple way is to make use of zip and *:
>>> ip = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
>>> print(list(zip(*ip)))
[(1, 2, 3), (1, 2, 3), (1, 2, 3)]
Suppose you have a matrix named m
transposed = zip(*m)
if your input isnumpy.array you may use the transpose:
i = np.array([[1,1,1], [2,2,2], [3,3,3]])
print(i.T)
output:
[[1 2 3]
[1 2 3]
[1 2 3]]
or you could use:
list(map(list, zip(*i)))

Python Numpy array creation from multiple lists

I am learning more about numpy and need help creating an numpy array from multiple lists. Say I have 3 lists,
a = [1, 1, 1]
b = [2, 2, 2]
c = [3, 3, 3]
How can I create a new numpy array with each list as a column? Meaning that the new array would be [[1, 2, 3], [1, 2, 3], [1, 2, 3]]. I know how to do this by looping through the lists but I am not sure if there is an easier way to accomplish this. The numpy concatenate function seems to be close but I couldn't figure out how to get it to do what I'm after.
Thanks
Try with np.column_stack:
d = np.column_stack([a, b, c])
No need to use numpy. Python zip does a nice job:
In [606]: a = [1, 1, 1]
...: b = [2, 2, 2]
...: c = [3, 3, 3]
In [607]: abc = list(zip(a,b,c))
In [608]: abc
Out[608]: [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
But if your heart is set on using numpy, a good way is to make a 2d array, and transpose it:
In [609]: np.array((a,b,c))
Out[609]:
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
In [610]: np.array((a,b,c)).T
Out[610]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
Others show how to do this with stack and column_stack, but underlying these is a concatenate. In one way or other they turn the lists into 2d arrays that can be joined on axis=1, e.g.
In [616]: np.concatenate([np.array(x)[:,None] for x in [a,b,c]], axis=1)
Out[616]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])

How to find missing combinations/sequences in a 2D array with finite element values

In the case of the set np.array([1, 2, 3]), there are only 9 possible combinations/sequences of its constituent elements: [1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3].
If we have the following array:
np.array([1, 1],
[1, 2],
[1, 3],
[2, 2],
[2, 3],
[3, 1],
[3, 2])
What is the best way, with NumPy/SciPy, to determine that [2, 1] and [3, 3] are missing? Put another way, how do we find the inverse list of sequences (when we know all of the possible element values)? Manually doing this with a couple of for loops is easy to figure out, but that would negate whatever speed gains we get from using NumPy over native Python (especially with larger datasets).
Your can generate a list of all possible pairs using itertools.product and collect all of them which are not in your array:
from itertools import product
pairs = [ [1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 1], [3, 2] ]
allPairs = list(map(list, product([1, 2, 3], repeat=2)))
missingPairs = [ pair for pair in allPairs if pair not in pairs ]
print(missingPairs)
Result:
[[2, 1], [3, 3]]
Note that map(list, ...) is needed to convert your list of list to a list of tuples that can be compared to the list of tuples returned by product. This can be simplified if your input array already was a list of tuples.
This is one way using itertools.product and set.
The trick here is to note that sets may only contain immutable types such as tuples.
import numpy as np
from itertools import product
x = np.array([1, 2, 3])
y = np.array([[1, 1], [1, 2], [1, 3], [2, 2],
[2, 3], [3, 1], [3, 2]])
set(product(x, repeat=2)) - set(map(tuple, y))
{(2, 1), (3, 3)}
If you want to stay in numpy instead of going back to raw python sets, you can do it using void views (based on #Jaime's answer here) and numpy's built in set methods like in1d
def vview(a):
return np.ascontiguousarray(a).view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
x = np.array([1, 2, 3])
y = np.array([[1, 1], [1, 2], [1, 3], [2, 2],
[2, 3], [3, 1], [3, 2]])
xx = np.array([i.ravel() for i in np.meshgrid(x, x)]).T
xx[~np.in1d(vview(xx), vview(y))]
array([[2, 1],
[3, 3]])
a = np.array([1, 2, 3])
b = np.array([[1, 1],
[1, 2],
[1, 3],
[2, 2],
[2, 3],
[3, 1],
[3, 2]])
c = np.array(list(itertools.product(a, repeat=2)))
If you want to use numpy methods, try this...
Compare the array being tested against the product using broadcasting
d = b == c[:,None,:]
#d.shape is (9,7,2)
Check if both elements of a pair matched
e = np.all(d, -1)
#e.shape is (9,7)
Check if any of the test items match an item of the product.
f = np.any(e, 1)
#f.shape is (9,)
Use f as a boolean index into the product to see what is missing.
>>> print(c[np.logical_not(f)])
[[2 1]
[3 3]]
>>>
Every combination corresponds to the number in range 0..L^2-1 where L=len(array). For example, [2, 2]=>3*(2-1)+(2-1)=4. Off by -1 arises because elements start from 1, not from zero. Such mapping might be considered as natural perfect hashing for this data type.
If operations on integer sets in NumPy are faster than operations on pairs - for example, integer set of known size might be represented by bit sequence (integer sequence) - then it is worth to traverse pair list, mark corresponding bits in integer set, then look for unset ones and retrieve corresponding pairs.

Choose certain items iterating through a list slice python

I have a list
[[0, 1], [1, 0], [0, 2], [1, 1], [2, 0], [0, 3], [1, 2], [2, 1], [3, 0]]
I would like to select the indices from the list that meet the following conditions:
1) The sum of the elements is equal to 3
2) The answer to the above sum does not appear in the list
The way I have thought to do this so far : create a new list with the sums of the above list, countersum, and take the indices, idx of those that meet the condition of being equal to 3, and then:
selection=[n for n, x in list[idx[0]:] if sum not in x]
So idx[0] should contain the index of the first element in the original list meeting the sum condition,
However this is giving me error and I have no idea why!
TypeError: argument of type 'int' is not iterable
Any help greatly appreciated!!
Here's a simple list comprehension:
>>> L = [[0, 1], [1, 0], [0, 2], [1, 1], [2, 0], [0, 3], [1, 2], [2, 1], [3, 0]]
>>> [i for i, j in enumerate(L) if sum(j) == 3 and 3 not in j]
[6, 7]
If I understand correctly, what you were trying to do was something like this:
[n for n, x in an_integer] # an_integer being an integer because that is what list[idx[0]:] returned
And you can't iterate through an integer, hence the error.

Sort a numpy array like a table

I have a list
[[0, 3], [5, 1], [2, 1], [4, 5]]
which I have made into an array using numpy.array:
[[0 3]
[5 1]
[2 1]
[4 5]]
How do I sort this like a table? In particular, I want to sort by the second column in ascending order and then resolve any ties by having the first column sorted in ascending order. Thus I desire:
[[2 1]
[5 1]
[0 3]
[4 5]]
Any help would be greatly appreciated!
See http://docs.scipy.org/doc/numpy/reference/generated/numpy.lexsort.html#numpy.lexsort
Specifically in your case,
import numpy as np
x = np.array([[0,3],[5,1],[2,1],[4,5]])
x[np.lexsort((x[:,0],x[:,1]))]
outputs
array([[2,1],[5,1],[0,3],[4,5]])
You can use numpy.lexsort():
>>> a = numpy.array([[0, 3], [5, 1], [2, 1], [4, 5]])
>>> a[numpy.lexsort(a.T)]
array([[2, 1],
[5, 1],
[0, 3],
[4, 5]])
Another way of doing this - slice out the bits of data you want, get the sort indices using argsort, then use the result of that to slice your original array:
a = np.array([[0, 3], [5, 1], [2, 1], [4, 5]])
subarray = a[:,1] # 3,1,1,5
indices = np.argsort(subarray) # Returns array([1,2,0,3])
result = a[indices]
Or, all in one go:
a[np.argsort(a[:,1])]
If you want to sort using a single column only (e.g., second column), you can do something like:
from operator import itemgetter
a = [[0, 3], [5, 1], [2, 1], [4, 5]]
a_sorted = sorted(a, key=itemgetter(1))
If there are more than one key, then use numpy.lexsort() as pointed out in the other answers.

Categories

Resources