I have a list of tuples, with nested tuples and lists, that looks like the list bellow:
a= [('Maria', [1, [2, {'teste': (2, 1.0)}]]),
('Lisa ', [2, [4, {'field': (4, 0.75), 'bola': (4, 0.25)}]]),
('John ', [4, [5, {'engine': (5, 0.2), 'wheel': (5, 0.4), 'wheels': (5, 0.2)}]]),
('Tracy ', [4, [6, {'pizza': (6, 0.16), 'fish': (6, 0.1), 'animals': (6, 0.1)}]])]
I want to flat out this list to look like:
a.modified = ('Maria', 1, 2, {'teste': (2, 1.0)}]]),
('Lisa ', 2, 4, {'field': (4, 0.75), 'bola': (4, 0.25)}]]),
('John ', 4, 5, {'engine': (5, 0.2), 'wheel': (5, 0.4), 'wheels': (5, 0.2)}]]),
('Tracy ', 4, 6, {'pizza': (6, 0.16), 'fish': (6, 0.1), 'animals': (6, 0.1}]])])
I have tried doing it step by step, using:
a2=[item for sublist in a for item in sublist]
and
a2 = list(itertools.chain.from_iterable(a))
and also:
a2 = list(item for sublist in a for item in sublist)
Nothing seems to work. I know this is too basic, but any tips on how to solve this would be really helpful. Thanks!
So it appears you have a list of tuples and linked-list-like structures. Whenever operating on linked-lists, you should think, recursion.
def flatten(items):
from itertools import chain
def flatten_link(link):
if isinstance(link, list):
yield link[0]
for item in flatten_link(link[1]):
yield item
elif link is not None:
yield link
return list(tuple(chain(item[:1], flatten_link(item[1]))) for item in items)
a = [
('Maria', [1, [2, {'teste': (2, 1.0)}]]),
('Lisa ', [2, [4, {'field': (4, 0.75), 'bola': (4, 0.25)}]]),
('John ', [4, [5, {'engine': (5, 0.2), 'wheel': (5, 0.4), 'wheels': (5, 0.2)}]]),
('Tracy', [4, [6, {'pizza': (6, 0.16), 'fish': (6, 0.1), 'animals': (6, 0.1)}]]),
]
print(flatten(a))
Which yields:
[
('Maria', 1, 2, {'teste': (2, 1.0)}),
('Lisa ', 2, 4, {'bola': (4, 0.25), 'field': (4, 0.75)}),
('John ', 4, 5, {'engine': (5, 0.2), 'wheel': (5, 0.4), 'wheels': (5, 0.2)}),
('Tracy', 4, 6, {'fish': (6, 0.1), 'animals': (6, 0.1), 'pizza': (6, 0.16)})
]
Related
I have the following sublist format:
x = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
y = [[11, 22, 33, 44], [55, 66, 77, 88], [99,100, 111, 122]...]
Above is a sublist containing the information of the "x" and "y" coordinates (the length can be changed accordingly).
Now I like take two sets and make pair of coordinates as following:
x_y = [[(1,11),(2,22),(3,33),(4,44)],[(5,55),(6,66),(7,77),(8,88)],[(9,99),(10,100),(11,111),(12,122)...]
any help would be appreciated. Thanks.
You could use zip twice:
x_y = [zip(a, b) for a, b in zip(x, y)]
print(x_y)
Output:
[[(1, 11), (2, 22), (3, 33), (4, 44)], [(5, 55), (6, 66), (7, 77), (8, 88)], [(9, 99), (10, 100), (11, 111), (12, 122)]]
I have the following sublist format:
mylist_x_y = [[1, 2, 3], [10, 20, 30]]
the [1, 2, 3] are X coordinates and the [10, 20, 30] Y coordinates.
Now I like them to be the following tuple format:
mylist_x_y_new = [(1, 10), (2, 20), (3, 30)]
Use zip with the list's elements:
mylist_x_y_new = zip(*mylist_x_y)
print(mylist_x_y_new)
Output:
[(1, 10), (2, 20), (3, 30)]
SS1=[(1, 2, 3, 4, 5), (1, 2, 3, 4, 6), (1, 2, 3, 5, 6), (1, 2, 4, 5, 6), (1, 3, 4, 5, 6), (2, 3, 4, 5, 6)]
SS2=[(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)]
SS3=[(1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
I'm Writing my list into a file using the below codes...But when i write again it's adding to the last line of the file.
but what i want is....it should append horizontally not vertically. I mean must go like table and fields and records.
so, for the above ss1 the line of records is going to be 6 and for every save should add the values in parallel as table fields and records manner
ss1 ss2 ss3
1, 2, 3, 4, 5 1, 2, 3, 4 1, 2, 3
def write_to_txt(a, file_name, delimiter=','):
with open(file_name, 'a') as f:
for k in SS1:
fmt = '%s' % delimiter
f.write(fmt.join(map(str, k)) + '\n')
not only writing and help me to read it back to same number of lists based on it's number columns.
def read_from_txt(file_name):
with open(file_name, 'r') as f:
data = [tuple(map(int, k.split(','))) for k in f.read().splitlines()]
return data
#write_to_txt(SS1, 'ABC.txt')
#data = read_from_txt('ABC.txt')
This is a good first aproach:
SS1=[(1, 2, 3, 4, 5), (1, 2, 3, 4, 6), (1, 2, 3, 5, 6), (1, 2, 4, 5, 6), (1, 3, 4, 5, 6), (2, 3, 4, 5, 6)]
SS2=[(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)]
SS3=[(1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
ALL = [SS1,SS2,SS3]
def write_to_txt(a, file_name, delimiter=','):
with open(file_name, 'a') as f:
for i, ss in enumerate(SS1):
if i != 0:
f.write("\n")
for ss in ALL:
fmt = '%s' % delimiter
f.write(fmt.join(map(str, ss[i])) + ",")
write_to_txt("a","lines.txt")
Unfortunately, that's not how text files work. If you wish to append "horizontally", what you really need to do is
Read each line of the file
Append your new value to each line (by concatenating the old string with a new one)
Write each new line of the file (now in write mode, not append). Note that this needs to be to a new file, or you should read your whole file first and overwrite it here.
Hope that helps.
For summation purposes, I created a list of tuples, where multiple items in the list have the same first variable.
for example:
x = [('m32',[1,2,3]),('m32',[2,3,4]),('m32',[4,5,6]),('m33',[1,2,3]),('m33',[2,3,4]),('m33',[4,5,6]),('m34',[1,2,3]),('m34',[2,3,4]),('m34',[4,5,6])....]
I want to add the individual values of the second items in the tuples (i.e 1+2+4, 2+3+5, 3+4+6) for all values that have the same first item (i.e. 'm32').
In other words, for all items labeled 'm32', I want to be able to add the other values.
How can I slice/index this to loop through and perform the summation?
Some tricky zip magic, along with itertools.groupby to group the matching first items together:
>>> x = [('m32',[1,2,3]),('m32',[2,3,4]),('m32',[4,5,6]),('m33',[1,2,3]),('m33',[2,3,4]),('m33',[4,5,6]),('m34',[1,2,3]),('m34',[2,3,4]),('m34',[4,5,6])]
>>> from itertools import groupby
>>> from operator import itemgetter
>>> for k,g in groupby(x,key=itemgetter(0)):
... print (k,[sum(i) for i in zip(*zip(*g)[1])])
...
('m32', [7, 10, 13])
('m33', [7, 10, 13])
('m34', [7, 10, 13])
A breakdown of how it works:
g is the group of items with matching keys. zip(*g) transposes the matrix, bringing the keys and values together:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*g)
...
[('m32', 'm32', 'm32'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
[('m33', 'm33', 'm33'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
[('m34', 'm34', 'm34'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
Getting the 2nd items:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*g)[1]
...
([1, 2, 3], [2, 3, 4], [4, 5, 6])
([1, 2, 3], [2, 3, 4], [4, 5, 6])
([1, 2, 3], [2, 3, 4], [4, 5, 6])
Transposing again to match up the items to sum:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*zip(*g)[1])
...
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
And adding them up:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print [sum(i) for i in zip(*zip(*g)[1])]
...
[7, 10, 13]
[7, 10, 13]
[7, 10, 13]
The answer given by Mark is great, and probably much more efficient that the one I'll post you. But I still want to post my answer because you are probably new to python and it will be easy for you to understand it.
For this kind of scripts you only need some imagination and basic python notions:
dictionary={}
for name, numbers in x:
if name in dictionary:
current_list=dictionary[name]
for i in range(3):
current_list[i]+=numbers[i]
else:
dictionary[name]=numbers
print(dictionary)
Note that the output is a dictionary:
{'m32': [7, 10, 13], 'm33': [7, 10, 13]}..
I hope it help you!
I am working on the question from this site, one of the question is asking to return Goldbach conjecture in a given range.
My answer works fine for small ranges, but for large range (e.g. 2 - 2000), it only return part of the solution like the following:
[(2, (2, 0)); (4, (2, 2)); (6, (3, 3)); (8, (3, 5)); (10, (3, 7));
(12, (5, 7)); (14, (3, 11)); (16, (3, 13)); (18, (5, 13)); (20, (3, 17));
(22, (3, 19)); (24, (5, 19)); (26, (3, 23)); (28, (5, 23)); (30, (7, 23));
(32, (3, 29)); (34, (3, 31)); (36, (5, 31)); (38, (7, 31)); (40, (3, 37));
(42, (5, 37)); (44, (3, 41)); (46, (3, 43)); (48, (5, 43)); (50, (3, 47));
(52, (5, 47)); (54, (7, 47)); (56, (3, 53)); (58, (5, 53)); (60, (7, 53));
(62, (3, 59)); (64, (3, 61)); (66, (5, 61)); (68, (7, 61)); (70, (3, 67));
(72, (5, 67)); (74, (3, 71)); (76, (3, 73)); (78, (5, 73)); (80, (7, 73));
(82, (3, 79)); (84, (5, 79)); (86, (3, 83)); (88, (5, 83)); (90, (7, 83));
(92, (3, 89)); (94, (5, 89)); (96, (7, 89)); (98, (9, 89)); (100, (3, 97));
(102, (5, 97)); (104, (3, 101)); (106, (3, 103)); (108, (5, 103));
(110, (3, 107)); (112, (3, 109)); (114, (5, 109)); (116, (3, 113));
(118, (5, 113)); (120, (7, ...)); ...]
I tried to use the solution provided by the website, but same thing happens. I wonder if there is a way to return the complete list of solutions.
Thanks!
I think you mean that the toplevel is only showing a prefix of the list. You can solve this by writing your own code to show the list.
Something like this would work:
let p (a, (b, c)) = Printf.printf "(%d, (%d, %d))\n" a b c
let printMyList l = List.iter p l
This is because the toplevel doesn't show values that are too long. You can change this lenght by using a pragma:
#print_length n;;
The other solution, perhaps better, is to write your own printing function. ;)