I have a tuple where my_tuple[0] contains an integer and my_tuple[1] contains 3 lists. So
my_tuple[0]=11
my_tuple[1]= [[1,2,3], [4,5,6], [7,8,9]]
for tuple_item in my_tuple[1]:
print tuple_item
How could I extract the lists from my_tuple[1] without using any external libraries (my current python interpreter has limitations)? I would like to be take the lists from the tuple and then create a dict of lists. Alternatively, I could do a list of lists
key=my_tuple[0]
#using the same key
my_dict[key]= list1
my_dict[key]= list2
my_dict[key]= list3
#or
for tuple_item in my_tuple[1]:
list_of_lists.append(tuple_item)
You need to generate a key for each list. In this example, I use the index of each list:
my_tuple = [None, None] # you need a list, otherwise you cannot assign values: mytuple = (None, None) is a tuple
my_tuple[0] = 11
my_tuple[1] = [[1,2,3], [4,5,6], [7,8,9]]
dict_of_lists = dict()
for i, tuple_item in enumerate(my_tuple[1]):
key = str(i) # i = 0, 1, 2; keys should be strings
dict_of_lists[key] = tuple_item
dict_of_lists
>> {'0': [1, 2, 3], '1': [4, 5, 6], '2': [7, 8, 9]}
Based on your comment in response to #Gijs, it sounds like you've got a perfectly good data structure already. Nonetheless, here's another:
#python3
from collections import namedtuple
Point = namedtuple("Point", "x, y, z")
Triangle = namedtuple("Triangle", "number, v1, v2, v3")
# Here is your old format:
my_tuple = (11, [ [1,2,3], [4,5,6], [7,8,9] ])
v1 = Point(*my_tuple[1][0])
v2 = Point(*my_tuple[1][1])
v3 = Point(*my_tuple[1][2])
num = my_tuple[0]
new_triangle = Triangle(num, v1, v2, v3)
print(new_triangle)
Output is:
Triangle(number=11, v1=Point(x=1, y=2, z=3), v2=Point(x=4, y=5, z=6), v3=Point(x=7, y=8, z=9))
You can use new_triangle.num and new_triangle.v1 to access members, and you can use new_triangle.v3.z to access submembers.
But I'll bet it won't be long before you wish you could loop over the vertices...
Related
I a set of lists and on those lists, I want to perform is to find the first occurence on an element on each list. Suppose I have the following lists:
D1 = [1,2,3,4,5]
D2 = [2,7,6,5,4]
D3 = [1,2,6,8,7]
Now for each list, I want to find out in what position the element 2 first occurs. In this respect, I have first stored the names of the lists in a separate list. I have done it using this code:
s_list = []
for i in range(1,4):
s_list.append('D'+str(i))
print(s_list)
Now, using these names, I want to perform the final operation using this code:
elem = 2
index_pos = []
for i in s_list:
k = i.index(elem)
index_pos.append(k)
print(index_pos)
However, on doing this, I get the following error:
TypeError: must be str, not int
I have tried str(i) instead of i but the error remains the same.
It would really be helpful if anyone can point out what I am doing wrong.
You can pack lists into a bigger list, so
lists = [D1, D2, D3]
and then iterate over that, so
elem = 2
index_pos = []
for l in lists:
k = l.index(elem)
index_pos.append(k)
print(index_pos)
The way you consider the list "D" into the s_list is not right and it is of type strings. Instead it could be done the following way.
Example:
D1 = [1,2,3,4,5]
D2 = [2,7,6,5,4]
D3 = [1,2,6,8,7]
s_list = [D1,D2,D3]
print(s_list)
Output:
[[1, 2, 3, 4, 5], [2, 7, 6, 5, 4], [1, 2, 6, 8, 7]]
Here the code is right and the same:
elem = 2
index_pos = []
for i in s_list:
k = i.index(elem)
index_pos.append(k)
print(index_pos)
Output:
[1, 0, 1]
The problem is that the elements of the list are strings. It is printed like:
['D1','D2','D3']
That is why you get an error. I suggest you define a function that takes some parameters and the return the indexes:
def retrun_indexes(ele,*args):
return [i.index(ele) for i in args if ele in i]
D1 = [1,2,3,4,5]
D2 = [2,7,6,5,4]
D3 = [1,2,6,8,7]
print(retrun_indexes(2,D1,D2,D3))
# Output: [1, 0, 1]
You can pass any number of list an it will return the result. Just make sure that always, the element to find is the first parameter to be passed in the function.
In this line for i in s_list: you are iterating over the s_list which just contains the names of the list as strings. Whereas really you want to iterate over the lists named D1, D2, D3 however these are variables.
So I think this fixes that problem by iterating over the lists themselves and their names at the same time.
D1 = [1,2,3,4,5]
D2 = [2,7,6,5,4]
D3 = [1,2,6,8,7]
s_list = []
for i in range(1,4):
s_list.append('D'+str(i))
index_pos = []
for d_list, list_name in zip([D1, D2, D3], s_list):
index_pos.append((d_list.index(2), list_name))
print(index_pos)
Out:
[(1, 'D1'), (0, 'D2'), (1, 'D3')]
Is there an efficient way to get the intersection of (the keys of) multiple dictionaries?
Similar to iterating over shared keys in two dictionaries , except the idea is not to iterate but rather get the set so it can be used to get the subset of dicts.
d1 = {'a':[1,2], 'b':[2,2]}
d2 = {'e':[3,2], 'b':[5,1], 'a':[5,5]}
d3 = {'b':[8,2], 'a':[3,3], 'c': [1,2]}
So intersection manually is simple
d1.keys() & d2.keys() & d3.keys()
but what about n-dimensional list? I feel like there is a better way than this:
d_list = [d1, d2, d3]
inter_keys = {}
for i in range(len(d_list)):
if i == 0:
inter_keys = d_list[i]
inter_keys = inter_keys & d_list[i].keys()
Then getting a subset
subsets = []
for n in d_list:
subsets.append( {k: n[k] for k in inter_keys} )
and finally use it to get the value subset
v = [ x.values() for x in subsets ]
really the last part is formatted as v = np.array([ np.array(list(x.values())) for x in subsets ]) to get the ndarray as:
[[[2 2] [1 2]]
[[5 1] [5 5]]
[[8 2] [3 3]]]
I was thinking there may be an approach using something like the numpy where to more efficiently get the subset, but not sure.
I think your code can be simplified to:
In [383]: d_list=[d1,d2,d3]
In [388]: inter_keys = d_list[0].keys()
In [389]: for n in d_list[1:]:
...: inter_keys &= n.keys()
...:
In [390]: inter_keys
Out[390]: {'a', 'b'}
In [391]: np.array([[n[k] for k in inter_keys] for n in d_list])
Out[391]:
array([[[1, 2],
[2, 2]],
[[5, 5],
[5, 1]],
[[3, 3],
[8, 2]]])
That is, iteratively get the intersection of keys, followed by extraction of the values into a list of lists, which can be made into an array.
inter_keys starts as a dict.keys object, but becomes a set; both work with &=.
I don't think there's a way around the double loop with dict indexing, n[k] as the core. Unless you can use the values or items lists, there isn't a way around accessing dict items one by one.
The sub_sets list of dict is an unnecessary intermediate step.
All the keys and values can be extracted into a list of lists, but that doesn't help with selecting a common subset:
In [406]: big_list = [list(d.items()) for d in d_list]
In [407]: big_list
Out[407]:
[[('a', [1, 2]), ('b', [2, 2])],
[('e', [3, 2]), ('b', [5, 1]), ('a', [5, 5])],
[('b', [8, 2]), ('a', [3, 3]), ('c', [1, 2])]]
Assuming that the lists of values in your dictionaries are of the same length, you can use this approach:
import numpy as np
d1 = {'a':[1,2], 'b':[2,2]}
d2 = {'e':[3,2], 'b':[5,1], 'a':[5,5]}
d3 = {'b':[8,2], 'a':[3,3], 'c':[1,2]}
d_list = [d1, d2, d3]
inter_map = {} if len(d_list) == 0 else d_list[0]
for d_it in d_list[1:]:
# combine element lists based on the current intersection. keys that do not match once are removed from inter_map
inter_map = {k: inter_map[k] + d_it[k] for k in d_it.keys() & inter_map.keys()}
# inter_map holds a key->value list mapping at this point
values = np.array([item for sublist in inter_map.values() for item in sublist]).reshape([len(inter_map.keys()),
2 * len(d_list)])
# real_values restructures the values into the order used in your program, assumes you always have 2 values per sublist
real_values = np.zeros(shape=[len(d_list), 2 * len(inter_map.keys())])
for i, k in enumerate(inter_map.keys()):
real_values[:, 2*i:2*(i+1)] = values[i].reshape([len(d_list), 2])
Please note that this code is not deterministic, since the order of keys in your map is not guaranteed to be the same for different runs of the program.
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
I want to split the following list of lists
a = [["aa",1,3]
["aa",3,3]
["sdsd",1,3]
["sdsd",6,0]
["sdsd",2,5]
["fffffff",1,3]]
into the three following lists of lists:
a1 = [["aa",1,3]
["aa",3,3]]
a2 = [["sdsd",1,3]
["sdsd",6,0]
["sdsd",2,5]]
a3 = [["fffffff",1,3]]
That is, according to the first value of each list. I need to do this for a list of lists with thousands of elements... How can I do it efficiently?
You're better off making a dictionary. If you really want to make a bunch of variables, you'll have to use globals(), which isn't really recommended.
a = [["aa",1,3]
["aa",3,3]
["sdsd",1,3]
["sdsd",6,0]
["sdsd",2,5]
["fffffff",1,3]]
d = {}
for sub in a:
key = sub[0]
if key not in d: d[key] = []
d[key].append(sub)
OR
import collections
d = collections.defaultdict(list)
for sub in a:
d[sub[0]].append(sub)
If input is sorted on first element:
from itertools import groupby
from operator import itemgetter
a = [["aa",1,3],
["aa",3,3],
["sdsd",1,3],
["sdsd",6,0],
["sdsd",2,5],
["fffffff",1,3]]
b = { k : list(v) for k, v in groupby(a, itemgetter(0))}
Create a dictionary with the first element as key and matching lists as value. And you will get a dictionary where value of each key value pair will be group of lists having same first element. For example,
a = [["aa", 1, 3],
["aa", 3, 3],
["sdsd", 1, 3],
["sdsd", 6, 0],
["sdsd", 2, 5],
["fffffff", 1, 3]]
d = {}
for e in a:
d[e[0]] = d.get(e[0]) or []
d[e[0]].append(e)
And now you can simply get the lists seperately,
a1 = d['aa']
a2 = d['sdsd']
A defaultdict will work nicely here:
a = [["aa",1,3],
["aa",3,3],
["sdsd",1,3],
["sdsd",6,0],
["sdsd",2,5],
["fffffff",1,3]]
from collections import defaultdict
d = defaultdict(list)
for thing in a:
d[thing[0]] += thing,
for separate_list in d.values():
print separate_list
Output
[['aa', 1, 3], ['aa', 3, 3]]
[['sdsd', 1, 3], ['sdsd', 6, 0], ['sdsd', 2, 5]]
[['fffffff', 1, 3]]
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]]