Python: uniqueness in list of lists - python

given à list of lists:
L = [[1,2,3], [3,4,5], [1,2,3]]
how to get a list where each list is unique:
L = [[1,2,3], [3,4,5]]
thanks

If you don't care about the order of sub-lists:
In [11]: list(map(list, set(map(tuple, L))))
Out[11]: [[3, 4, 5], [1, 2, 3]]
Better yet, you should probably just move to using sets of tuples as your data structure.

Bit of jinking around but how about this?
[list(el) for el in set(tuple(el) for el in L)]
It works because lists can't be compared to one another but tuples can. The error message gives it away if you try to directly make a set from a list of lists:
unhashable type: 'list'

L = [[1,2,3], [3,4,5], [1,2,3]]
newlist = []
for item in L:
if item not in newlist:
newlist.append(item)

You can convert to a set of tuples and then back to a list.
L = [[1,2,3], [3,4,5], [1,2,3]]
setL = set(tuple(i) for i in L)
newL = list(list(i) for i in setL)
print newL
[[3, 4, 5], [1, 2, 3]]

Related

flat 2d to 1d array

I have a list with a list inside.
Can you please help me - how to change the list of lists to list?
I tried with nd.array reshape(), flatten(), and ravel(), but no luck
Input:
['Test', [1, 2]]
Expected result:
['Test', 1, 2]
This problem is known as flattening an irregular list. There are a few ways you can do this -
Using list comprehension
l = ['Test', [1, 2]]
regular_list = [i if type(i)==list else [i] for i in l]
flatten_list = [i for sublist in regular_list for i in sublist]
flatten_list
['Test', 1, 2]
Using nested for loops
out = []
for i in l:
if type(i)==list:
for j in i:
out.append(j)
else:
out.append(i)
print(out)
['Test', 1, 2]
There are multiple answers, depending on context and preference:
For python lists:
flattened_list = [element for sublist in input_list for element in sublist]
# or:
import itertools
flattened_list = itertools.chain(*input_list)
Or, if you are using numpy.
flattened_list = list(original_array.flat)
# or, if you need it as a numpy array:
flattened_array = original_array.flatten()
You can try this:
li = ['Test', [1, 2]]
merged = []
for x in li:
if not isinstance(x, list):
merged.append(x)
else:
merged.extend(x)
print(merged)
Output: ['Test', 1, 2]

Creating a loop of many lists

I have a list of data:
data_list = [[1,2,3], [4,5,6], [7,8,9], ...]
I am trying to assign each element to a separate list so that:
Bin1 = [1,2,3]
Bin2 = [4,5,6]
....
Bin100 = [..,..,..]
I'm not sure how to do this without doing the manual way of initializing lists 1 by 1. Tried searching for a function how to go about it but have not found anything.
Once I have the lists initialized, I'd need to append the data from data_list:
for i in range(0, len(data_list)):
bin1.append(data_list[i][1])
bin2.append(data_list[i][2])
.......
Again, a shortcut way of doing this would be so useful!
You could use a dictionary if you wanted to access the lists with a key like "Bin1":
data_list = [[1,2,3], [4,5,6], [7,8,9]]
d = {}
for i, v in enumerate(data_list, 1):
d['Bin{}'.format(i)] = v
print(d) # >>> {'Bin1': [1, 2, 3], 'Bin3': [7, 8, 9], 'Bin2': [4, 5, 6]}
print(d['Bin1']) # >>> [1, 2, 3]
Or using a dict comprehension:
d = {'Bin{}'.format(i): v for i,v in enumerate(data_list, 1)}
you can simply write below code
l = [ [i,i+1,i+2] for i in range(1,YOUR_MAX_LENGTH,3) ]
hope this helps
Use dictionary comprehension to make a dictionary of lists, note this makes copies:
data_list = [[1,2,3], [4,5,6], [7,8,9]]
# To make copies
separate_lists = {'bin'+str(i): sublist
for i,sublist in enumerate(data_list,1)}
print (separate_lists)
To make a dictionary without making copies, this should work:
# To remove sublists from data_list and put them in the dictionary
separate_lists_not_copied = {}
for i in range(1,len(data_list)+1):
separate_lists_not_copied['bin'+str(i)] = data_list.pop(0)
print (separate_lists_not_copied)
Both print:
{'bin3': [7, 8, 9], 'bin1': [1, 2, 3], 'bin2': [4, 5, 6]}
use locals() to create variable name on-the-fly and iterate over all your sublists.
For those who are not aware of this function:
Update and return a dictionary representing the current local symbol table.
Free variables are returned by locals() when it is called in function
blocks, but not in class blocks.
data_list = [[1,2,3], [4,5,6], [7,8,9]]
for i, sublist in enumerate(data_list, 1):
locals()['bin_{}'.format(i)] = sublist
print bin_1 # [1, 2, 3]
print bin_3 # [7,8,9]
NOTE: Don't use uppercase on variable name since it is use by convention on for python classes. so bin_1 is a better name than Bin1

mapping the append function to a list

I want to do the following elegantly. I have a list:
list1 = [[1,2],[3,1,4,7],[5],[7,8]]
I'd like to append the number 1 to each element of the list, so that I have
list1 = [[1,2,1],[3,1,4,7,1],[5,1],[7,8,1]]
I'm trying to map this via
map(list.append([1]), vectors)
but this returns the error append() takes exactly one argument (0 given) and if I just try append([1]) (without list.), I get NameError: global name 'append' is not defined. I guess I could do it with a loop, but this seems more elegant, is there a way to map this correctly?
Here is a several ways to implement what you want:
More readable and classic way
for el in list1:
el.append(1)
List comprehension
list1 = [el + [1] for el in list1]
Generators:
list1 = (el + [1] for el in list1)
Map
list1 = map(lambda el: el + [1], list1)
What to use?
It depends on you own situation and may depends on execution speed optimizations, code readability, place of usage.
Map is a worst choice in case of readability and execution speed
For is a fastest and more plain way to do this
Generators allows you to generate new list only when you really need this
List comprehension - one liner for classic for and it takes advantage when you need quickly filter the new list using if
i.e. if you need only add element to each item - for loop is a best choice to do this, but if you need add item only if item > 40, then you may consider to use List comprehension.
For example:
Classic For
x = 41
for el in list1:
if x > 40:
el.append(x)
List comprehension
x = 1
list1 = [el + [x] for el in list1 if x > 40]
as #jmd_dk mentioned, in this sample is one fundamental difference: with simple for you can just append to an existing object of the list which makes much less impact to execution time and memory usage. When you use List comprehension, you will get new list object and in this case new list object for each item.
Try a list comprehension, taking advantage of the fact the adding lists concats them together.
new_list = [l + [1] for l in list1]
You can simply do
list1 = [[1,2],[3,1,4,7],[5],[7,8]]
for el in list1:
el.append(1)
map(lambda x: x + [1], list1)
you mean this?
list.append() have NO return (mean always return None)
With list comprehension and append, you can do:
list1 = [[1, 2], [3, 1, 4, 7], [5], [7, 8]]
[item.append(1) for item in list1]
print(list1) # Output: [[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]
Output:
>>> list1 = [[1, 2], [3, 1, 4, 7], [5], [7, 8]]
>>> [item.append(1) for item in list1]
[None, None, None, None]
>>> list1
[[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]
You may also use extend like this:
[item.extend([1]) for item in list1]
print(list1) # Output: [[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]

python 2-D list how to make a set [duplicate]

This question already has answers here:
How to remove duplicate lists in a list of list? [duplicate]
(2 answers)
Closed 6 years ago.
as a python list follow
list1 = [[1,2],[3,4],[1,2]]
I want make a set so I can the unique list items like
list2 = [[1,2],[3,4]].
Is there some function in python I can use. Thanks
That will do:
>>> list1 = [[1,2],[3,4],[1,2]]
>>> list2 = list(map(list, set(map(tuple,list1))))
>>> list2
[[1, 2], [3, 4]]
Unfortunately, there is not a single built-in function that can handle this. Lists are "unhashable" (see this SO post). So you cannot have a set of list in Python.
But tuples are hashable:
l = [[1, 2], [3, 4], [1, 2]]
s = {tuple(x) for x in l}
print(s)
# out: {(1, 2), (3, 4)}
Of course, this won't help you if you want to later, say, append to these lists inside your main data structure, as they are now all tuples. If you absolutely must have the original list functionality, you can check out this code recipe for uniquification by Tim Peters.
Note that this only removes duplicate sublists, it does not take into account the sublist's individual elements. Ex: [[1,2,3], [1,2], [1]] -> [[1,2,3], [1,2], [1]]
>>> print map(list, {tuple(sublist) for sublist in list1})
[[1, 2], [3, 4]]
You can try this:
list1 = [[1,2],[3,4],[1,2]]
list2 = []
for i in list1:
if i not in list2:
list2.append(i)
print(list2)
[[1, 2], [3, 4]]
The most typical solutions have already been posted, so let's give a new one:
Python 2.x
list1 = [[1, 2], [3, 4], [1, 2]]
list2 = {str(v): v for v in list1}.values()
Python 3.x
list1 = [[1, 2], [3, 4], [1, 2]]
list2 = list({str(v): v for v in list1}.values())
There is no inbuilt single function to achieve this. You have received many answers. In addition to those, you may also use a lambda function to achieve this:
list(map(list, set(map(lambda i: tuple(i), list1))))

Turning a list into nested lists in python

Possible Duplicate:
How can I turn a list into an array in python?
How can I turn a list such as:
data_list = [0,1,2,3,4,5,6,7,8]
into a list of lists such as:
new_list = [ [0,1,2] , [3,4,5] , [6,7,8] ]
ie I want to group ordered elements in a list and keep them in an ordered list. How can I do this?
Thanks
This groups each 3 elements in the order they appear:
new_list = [data_list[i:i+3] for i in range(0, len(data_list), 3)]
Give us a better example if it is not what you want.
This assumes that data_list has a length that is a multiple of three
i=0
new_list=[]
while i<len(data_list):
new_list.append(data_list[i:i+3])
i+=3
Something like:
map (lambda x: data_list[3*x:(x+1)*3], range (3))
Based on the answer from Fred Foo, if you're already using numpy, you may use reshape to get a 2d array without copying the data:
import numpy
new_list = numpy.array(data_list).reshape(-1, 3)
new_list = [data_list[x:x+3] for x in range(0, len(data_list) - 2, 3)]
List comprehensions for the win :)
The following function expands the original context to include any desired list of lists structure:
def gen_list_of_lists(original_list, new_structure):
assert len(original_list) == sum(new_structure), \
"The number of elements in the original list and desired structure don't match"
list_of_lists = [[original_list[i + sum(new_structure[:j])] for i in range(new_structure[j])] \
for j in range(len(new_structure))]
return list_of_lists
Using the above:
data_list = [0,1,2,3,4,5,6,7,8]
new_list = gen_list_of_lists(original_list=data_list, new_structure=[3,3,3])
# The original desired outcome of [[0,1,2], [3,4,5], [6,7,8]]
new_list = gen_list_of_lists(original_list=data_list, new_structure=[2,3,3,1])
# [[0, 1], [2, 3, 4], [5, 6, 7], [8]]
The below one is more optimized and quite straightforward.
data_list = [0,1,2,3,4,5,6,7,8]
result =[]
i=0
while i <(len(data_list)-2):
result.append(data_list[i:i+3])
i+=3
print(result)
**output**
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
Here is a generalized solution
import math
data_list = [0,1,2,3,4,5,6,7,8]
batch_size=3
n_batches=math.ceil(len(data_list)/batch_size)
[data_list[x*batch_size:min(x*batch_size+batch_size,len(data_list))]
for x in range(n_batches)]
It works even if the last sublist is not the same size as the rest (<batch_size)
Do you have any sort of selection criteria from your original list?
Python does allow you to do this:
new_list = []
new_list.append(data_list[:3])
new_list.append(data_list[3:6])
new_list.append(data_list[6:])
print new_list
# Output: [ [0,1,2] , [3,4,5] , [6,7,8] ]

Categories