How to remove identical lists from a list of lists? - python

I'd like to remove same lists in a list having len(a) = 5 and a = [[1,2,3],[2,3,4], [0,1,2],[2,4,6],[3,6,9]] as results.
How can I get that?
a1 = [[1,2,3],[2,3,4]]
a2 = [[0,1,2],[2,4,6]]
a3=[[1,2,3],[0,1,2],[3,6,9]]
a = a1+a2+a3
a = [tuple(l) for l in a]
print(set(a))
print(len(a))
a=[list(ele) for ele in a]
print(a)
print(len(a))

You cannot make a set of lists of lists because they are not hashable. You could first convert them to tuples and then create a set:
a1 = [[1,2,3],[2,3,4]]
a2 = [[0,1,2],[2,4,6]]
a3=[[1,2,3],[0,1,2],[3,6,9]]
a = a1+a2+a3
a = [list(x) for x in set([tuple(L) for L in a])]
output:
[[0, 1, 2], [2, 4, 6], [1, 2, 3], [2, 3, 4], [3, 6, 9]]

Related

How to get those elements which are at the same position in two 2D matrix in Python using a filter?

I am trying to get the elements as a list if any of them in the same position in two 2D matrices.
Let's consider matrix A and matrix B
A = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4],[7, 8, 1]]
The resultant list should be
C = [2, 7, 8]
I have tried using a filter but it is not working.
def find(A):
for i in range(3):
for j in range(3):
if A[i][j] == B[i][j]:
return A[i][j]
else:
return False
A = [[1, 2, 3],[4, 5, 6], [7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4], [7, 8, 1]]
C = filter(find, A)
for element in C:
print(element)
Note: Please use a filter to achieve the target.
Solution using filter:
def find(L):
A, B = L
if A == B:
return True
else:
return False
A = [[1, 2, 3],[4, 5, 6], [7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4], [7, 8, 1]]
# flatten lists
A = [item for row in A for item in row]
B = [item for row in B for item in row]
C = filter(find, zip(A,B))
# filter returns a tuple for each row but we only want the single element
C = [item[0] for item in C]
print(list(C))
Gives us
[2, 7, 8]
Try this,
def func(t):
return True if t[0] == t[1] else False
A = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4],[7, 8, 1]]
C = [item1 for lst1, lst2 in zip(A, B) for item1, item2 in filter(func, zip(lst1, lst2))]
>>> C
[2, 7, 8]
Basic Answer
First we loop over A and B, i and z now holds the inner lists.
Then we loop over those inner lists using g and q, if they are equal, we append them to the empty list.
to_fill = []
for i,z in zip(A,B):
for g,q in zip(i,z):
if g==q:
to_fill.append(g)
Adapt it as you please.
The most efficient way of achieving what you want is by using numpy:
import numpy as np
A = np.asarray(A)
B = np.asarray(B)
C = A[A==B]

Python: Appending numerous 2D list to one 2D list

For the sake of simplicity I will just use two lists.
So I have the following 2D lists:
> > a = [[1,2,3],
> > [1,2,3]]
> > b = [[4,5,6],
> > [4,5,6]]
And if I append list a and b, I'm looking to obtain the following:
masterlist = [[1,4], [2,5], [3,6], [1,4], [2,5], [3,6]]
The following code is what I have tried:
filenames = [a,b] #For the example, since I will have multiple arrays
masterlist = []
counter = 0
for file in filenames:
if counter == 0: #This if is to try to create lists within the list
for row in file: #This loops is to iterate throughout the whole list
for col in row:
c = [masterlist.append([col])]
[masterlist.append(c) for row, col in zip(masterlist, c)]
counter = 1
else: #This else is to append each element to their respective position
for row in file:
for col in row:
c = [masterlist.append(col)]
[masterlist.append([c]) for row, col in zip(masterlist, c)]
The output when printing masterlist is the following:
[[1], [2], [3], [1], [2], [3], [None], 4, 5, 6, 4, 5, 6, [[None]]]
I'm not sure where the [None]'s come from either. And as we can see '4,5,6...' aren't appended to the lists '[1], [2], [3]...' respectively.
You can iterate through the items of the lists and then add them to your masterlist:
a = [[1,2,3],
[1,2,3]]
b = [[4,5,6],
[4,5,6]]
masterlist = []
for aa,bb in zip(a,b): # loop over lists
for itema, itemb in zip(aa,bb): # loop over items in list
masterlist = masterlist + [[itema, itemb]]
output:
[[1, 4], [2, 5], [3, 6], [1, 4], [2, 5], [3, 6]]
If you use numpy,this is really easy
import numpy as np
a = np.array([[1,2,3],
[1,2,3]])
b = np.array([[4,5,6],
[4,5,6]])
fl = np.vstack(np.dstack((a,b)))
output
array([[1, 4],
[2, 5],
[3, 6],
[1, 4],
[2, 5],
[3, 6]])

Creating a nested list inside a nested list in python

I have this nested list:
list_1 = [[1,2,3], [1,2,3,4,5,6], [1,2,3,4,5,6,7,8,9]]
Count of sublist elements are always in mulitple of 3. I want to have 3 elments in each sublist. Desired output:
list_1 = [[1,2,3], [1,2,3], [4,5,6],[1,2,3], [4,5,6], [7,8,9]]
I can achieve this but first i have to flatten the list and then create the nested list. My code:
list_1 = [values for sub_list in lists_1 for values in sub_list] # flatten it first
list_1 = [list_1[i:i+3] for i in range(0, len(list_1), 3)]
Is there a way to skip the flatten step and get the desired result?
You can use a nested list comprehension:
list_1 = [[1,2,3], [1,2,3,4,5,6], [1,2,3,4,5,6,7,8,9]]
result = [i[j:j+3] for i in list_1 for j in range(0, len(i), 3)]
Output:
[[1, 2, 3], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
Here is how you can use nested list comprehensions:
list_1 = [[1,2,3],[1,2,3,4,5,6],[1,2,3,4,5,6,7,8,9]]
list_1 = [a for b in list_1 for a in b]
list_1 = [list_1[i:i+3] for i in range(0,len(list_1),3)]
print(list_1)
Output:
[[1, 2, 3], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
To put my two cents in, you could use two generator functions, one that flattens the list (with an arbitrarly nested list) and one that yields pairs of n values:
def recursive_yield(my_list):
for item in my_list:
if isinstance(item, list):
yield from recursive_yield(item)
else:
yield item
def taken(gen, number = 3):
buffer = []
for item in gen:
if len(buffer) < number:
buffer.append(item)
else:
yield buffer
buffer = []
buffer.append(item)
if buffer:
yield buffer
result = [x for x in taken(recursive_yield(list_1))]
Here are some examples of the in- / outputs:
list_1 = [[1,2,3], [1,2,3,4,5,6], [1,2,3,4,5,6,7,8,9]]
# -> [[1, 2, 3], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
list_1 = [1,2,3,4,5,6]
# -> [[1, 2, 3], [4, 5, 6]]
list_1 = [1,2,[[1,2,4,5], [[[[1,10,9]]]]]]
# -> number = 5
# -> [[1, 2, 1, 2, 4], [5, 1, 10, 9]]
Thus, the solution is much more flexible than slicing alone.

Concatenating list with nested list

a = [1, 2]
b = [[5,6], [7,8]]
c = list(zip(a, b))
print("c zipped:", c)
i = 0
lenghta = len(a)
c = []
while i < lengtha:
temp_list = [a[i], b[i]]
c.append(temp_list)
i += 1
print("c: ", c)
output:
c zipped: [(1, [5, 6]), (2, [7, 8])] c: [[1, [5, 6]], [2, [7, 8]]]
What I am expecting is:
[[1, 5, 6], [2, 7, 8]]
This seems overcomplicated. Try this, using a list comprehension:
a = [1, 2]
b = [[5,6], [7,8]]
c = [[x] + b[i] for i, x in enumerate(a)]
I know this isn't using zip(), but you could do:
c = []
for i in range(len(a)):
c.append([a[i], b[i]])
Using zip and list comprehension
a = [1, 2]
b = [[5,6], [7,8]]
[[i]+j for i,j in zip(a,b)]
#[[1, 5, 6], [2, 7, 8]]
you can also use itertools.chain
>>> from itertools import chain
>>> a = [1, 2]
>>> b = [[5,6], [7,8]]
>>> c = [list(chain([x], y)) for (x, y) in zip(a, b)]
>>> c
[[1, 5, 6], [2, 7, 8]]

Python print unique arrays from an array

I am trying to print a unique set of arrays from an array while keeping the array in order.
Example array:
[[1,2,3], [1,3,2], [1,2,3], [3,1,2]]
The output that I am looking for is:
[[1,2,3], [1,3,2], [3,1,2]]
I've looked at converting the array into a set but it appears that it has issues with a 2D array (I believe it compares each element individually which if it could run, it would result in simply [1,2,3]) also, I am reading that it does not keep the order of the values.
You need simple check if an element in the rest of your array and get rid of it. To preserve order, loop should go backwards:
array = [[1,2,3], [1,3,2], [1,2,3], [3,1,2]]
for a_ind in range((len(array)-1), 0, -1):
if (array[a_ind] in array[:a_ind]):
array.pop(a_ind)
print (array)
# [[1, 2, 3], [1, 3, 2], [3, 1, 2]]
Use a nested for-loop to see if an element has been seen already:
data = [[1,2,3], [1,3,2], [1,2,3], [3,1,2]]
processed = []
for i in range(len(data)):
for j in range(i):
if data[i] == data[j]:
break
else:
processed.append(data[i])
print(processed) # Should be [[1,2,3], [1,3,2], [3,1,2]]
Try something like this:
>>> u = [[1,2,3], [1,3,2], [1,2,3], [3,1,2]]
>>> unique = []
>>> (unique.append(x) for x in u if x not in unique)
<generator object <genexpr> at 0x103df4620>
>>> print(unique)
[[1, 2, 3], [1, 3, 2], [3, 1, 2]]
Solution 1: using dictionary to get rid of the lists that got the same elements
a = [[1, 2, 3], [1, 3, 2], [1, 2, 3], [3, 1, 2]]
d = {}
for k in a:
d[str(k)] = k
a = []
for v in d.values():
a += [v]
print(a)
output*
[[1, 3, 2], [1, 2, 3], [3, 1, 2]]
using a dictionary, this one can have the lists in the list in a different order each time you execute the script.
Solution 2: looking into the list to pop the one that got the same order of elements
b = [[1, 2, 3], [1, 3, 2], [1, 2, 3], [3, 1, 2]]
for l in b:
if l in b[b.index(l) + 1:]:
b.pop(b.index(l))
print(b)
output
[[1, 3, 2], [1, 2, 3], [3, 1, 2]]
Instead of doing for loops, you can:
class Foo(object):
def __init__(self, a_list):
self._list = list(a_list)
def __str__(self):
return str(self._list)
def __repr__(self):
return self.__str__()
def __eq__(self, other):
return all([i1 == i2 for i1, i2 in zip(self, other)])
def __ne__(self, other):
return any([i1 != i2 for i1, i2 in zip(self, other)])
def __hash__(self):
return 0
def __iter__(self):
return iter(self._list)
a1 = Foo([1, 2, 3])
a2 = Foo([1, 3, 2])
a3 = Foo([1, 2, 3])
a4 = Foo([3, 2, 1])
c = [a1, a2, a3, a4]
print(list(set(c)))
# Output
[[1, 2, 3], [1, 3, 2], [3, 2, 1]]
__str__ and __repr__ methods are for the output and __iter__ for the list comprehension.
Online: https://repl.it/BqAS/0

Categories

Resources