How to sum elements in a nested list? - python

I want to sum elements I [1] (second elements in each list) in the nested list so that it doesn't exceed 23, i.e. <= 23 and create a sublist from that. Now I only get the same list, but I want a list where the total value doesn't exceed 23:
this = [['A', 5, 310],['B', 3, 270], ['C', 4.5, 220], ['D', 1, 150], ['E', 3.5, 140], ['F', 2.5, 90], ['G', 4, 70], ['H', 3, 60], ['I', 2, 50], ['J', 1, 30]]
max_weight = [i for i in this if i[1]<=23]
print(max_weight)

do you want to do a sum from all items?
max_weight = sum(i[1] for i in this if i[1]<=23)
print(max_weight) #29.5
EDIT:
i think you want to do this, (I'm not sure if its possible to do in a one-liner)
this = [['A', 5, 310],['B', 3, 270], ['C', 4.5, 220], ['D', 1, 150], ['E', 3.5, 140], ['F', 2.5, 90], ['G', 4, 70], ['H', 3, 60], ['I', 2, 50], ['J', 1, 30]]
total = 0
new = []
for i in this:
total += i[1]
if total <= 23:
new.append(i)
print(new) #[['A', 5, 310], ['B', 3, 270], ['C', 4.5, 220], ['D', 1, 150], ['E', 3.5, 140], ['F', 2.5, 90]]

Related

How to interchange the values in a list of lists?

I have a list of lists. I need to interchange the values inside each one.
For example: ['a', 12] to [12, 'a']
Input:
x = [['a', 12],
['b', 14],
['c', 22],
['d', 29],
['e', 29],
['f', 29],
['g', 29],
['h', 30],
['i', 2],
['j', 8]]
My expected output:
y = [[12, 'a'],
[14, 'b'],
[22, 'c'],
[29, 'd'],
[29, 'e'],
[29, 'f'],
[29, 'g'],
[30, 'h'],
[2, 'i'],
[8, 'j']]
[i[::-1] for i in list_change]
Here you go :
list_change = [['a', 12],['b', 14],['c', 22],['d', 29]]
new_list_change = [[sublist[1], sublist[0]] for sublist in list_change]
lst = [['a', 12], ['b', 14], ['c', 22], ['d', 29]]
print([[item[1], item[0]] for item in lst])
[[num, let] for let, num in list_change]
In the following solution the lists are not reconstructed. The data are changed "in place". This may be wanted or unwanted if any other variable is pointing to one of the small lists in the list.
for i in range(len(mylist)):
a, b = mylist[i]
mylist[i][:] = b, a
If you want to leave everything in place, but generate a new list with swapped elements, use r.ook's answer or—if you think that list comprehension is hard to read—this:
newlist = []
for a, b in oldlist:
newlist.append([b, a])

Create dict using a grouping column in an array and assigning the remaining columns to values of the dict

I have a type(s1) = numpy.ndarray. I want to create a dictionary by using the first column of s1 as key and rest as values to the key. The first column has repeated values.
Here is np.array.
s1 = np.array([[1L, 'R', 4],
[1L, 'D', 3],
[1L, 'I', 10],
[1L, 'K', 0.0],
[2L, 'R', 11],
[2L, 'D', 13],
[2L, 'I', 1],
[2L, 'K', 6],
[3L, 'R', 12],
[3L, 'D', 17],
[3L, 'I', 23],
[3L, 'K', 10]], dtype=object)
I want to get the following:
{'1':[['R',4],['D',3],['I',10],['K',0]],
'2':[['R',11],['D',13],['I',1],['K',6]],
'3':[['R',12],['D',17],['I',23],['K',10]]}
This is what I tried and got:
In [18]: {x[0]:[x[1],x[2]] for x in s1}
Out[18]: {1L: ['K', 0.0], 2L: ['D', 6], 3L: ['K', 10]}
I see the problem that the grouping column has repeated values. But I am unable to do the appending. What is the trick I am missing?
You can simply built them with defaultdict :
d=collections.defaultdict(list)
for k,*v in s1 : d[k].append(list(v))
for
defaultdict(list,
{1: [['R', 4], ['D', 3], ['I', 10], ['K', 0.0]],
2: [['R', 11], ['D', 13], ['I', 1], ['K', 6]],
3: [['R', 12], ['D', 17], ['I', 23], ['K', 10]]})
EDIT
You can nest dicts in dicts :
d=collections.defaultdict(dict)
for k1,k2,v in s1 : d[k1][k2]=v
#defaultdict(dict,
# {1: {'D': 3, 'I': 10, 'K': 0.0, 'R': 4},
# 2: {'D': 13, 'I': 1, 'K': 6, 'R': 11},
# 3: {'D': 17, 'I': 23, 'K': 10, 'R': 12}})
In [67]: d[2]['K']
Out[67]: 6
See here for generalization.
You might want to use itertools.groupby():
In [15]: {k: [list(x[1:]) for x in g]
....: for k,g in itertools.groupby(s1, key=lambda x: x[0])}
Out[15]:
{1L: [['R', 4], ['D', 3], ['I', 10], ['K', 0.0]],
2L: [['R', 11], ['D', 13], ['I', 1], ['K', 6]],
3L: [['R', 12], ['D', 17], ['I', 23], ['K', 10]]}

Merge function will only work for ordered list

I have this 2 lists as input:
list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]
list2 = [['A', 14, 'Y', 0, 200], ['B', 15, 'M', 0, 400], ['C', 17, 'G', 0, 600]]
and my desired output will be this:
finalList = [['A', 14, 'Y', 10, 200], ['B', 15, 'M', 30, 400], ['C', 16, 'F', 50, 60],['C', 17, 'G', 0, 600]]
Using this function:
def custom_merge(list1, list2):
finalList = []
for sub1, sub2 in zip(list1, list2):
if sub1[1]==sub2[1]:
out = sub1.copy()
out[2] = sub2[2]
out[4] = sub2[4]
finalList.append(out)
else:
finalList.append(sub1)
finalList.append(sub2)
return finalList
I will get indeed my desired output, but what if I switch positions (list2[1] and list2[2]) and my list2:
list2 = [['A', 14, 'Y', 0, 200], ['C', 17, 'G', 0, 600], ['B', 15, 'M', 0, 400]]
Then the output will be this:
[['A', 14, 'Y', 10, 200], ['B', 15, 'S', 30, 40], ['C', 17, 'G', 0, 600], ['C', 16, 'F', 50, 60], ['B', 15, 'M', 0, 400]]
(notice the extra ['B', 15, 'M', 0, 400])
What I have to modify in my function in order to get my first desired output if my lists have a different order in my list of lists!? I use python 3. Thank you!
LATER EDIT:
Merge rules:
When list1[listindex][1] == list2[listindex][1] (ex: when 14==14), replace in list1 -> list2[2] and list2[4] (ex: 'Y' and 200) and if not just add the unmatched list from list2 to list1 as it is (like in my desired output) and also keep the ones that are in list1 that aren't matched(ex: ['C', 16, 'F', 50, 60])
To be noted that list1 and list2 can have different len (list1 can have more lists than list2 or vice versa)
EDIT.2
I found this:
def combine(list1,list2):
combined_list = list1 + list2
final_dict = {tuple(i[:2]):tuple(i[2:]) for i in combined_list}
merged_list = [list(k) + list (final_dict[k]) for k in final_dict]
return merged_list
^^ That could work, still testing!
You can sort the lists by the first element in the sublists before merging them.
def custom_merge(list1, list2):
finalList = []
for sub1, sub2 in zip(sorted(list1), sorted(list2)):
if sub1[1]==sub2[1]:
out = sub1.copy()
out[2] = sub2[2]
out[4] = sub2[4]
finalList.append(out)
else:
finalList.append(sub1)
finalList.append(sub2)
return finalList
tests:
list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]
list2 = [['A', 14, 'Y', 0, 200], ['C', 17, 'G', 0, 600], ['B', 15, 'M', 0, 400]]
custom_merge(list1, list2)
# returns:
[['A', 14, 'Y', 10, 200],
['B', 15, 'M', 30, 400],
['C', 16, 'F', 50, 60],
['C', 17, 'G', 0, 600]]

Join operation of 2 lists of lists based on index

I have this 2 list of lists:
list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]
list2 = [['A', 14, 'Y', 0, 200], ['B', 15, 'M', 0, 400], ['C', 17, 'G', 0, 600]]
(this is just a sample with only 3 lists, I have more lists but they are on the exact same format and apply same rules)
And this will be my desired output:
finalList = [['A', 14, 'Y', 10, 200], ['B', 15, 'M', 30, 400], ['C', 16, 'F', 50, 60],['C', 17, 'G', 0, 600]]
This is the rule how I compute finalList:
When list1[listindex][1] == list2[listindex][1] (ex: when 14==14), replace in list1 -> list2[2] and list2[4] (ex: 'Y' and 200) and if not just add the unmatched list from list2 to list1 as it is (like in my desired output) and also keep the ones that are in list1 that aren't matched(ex: ['C', 16, 'F', 50, 60]).
How I can do this in a python 3 function? I would like a simple and straight forward function for this. Thank you so much for your time!
You can apply all of your rules using if statements in a function.
def custom_merge(list1, list2):
finalList = []
for sub1, sub2 in zip(list1, list2):
if sub1[1]==sub2[1]:
out = sub1.copy()
out[2] = sub2[2]
out[4] = sub2[4]
finalList.append(out)
else:
finalList.append(sub1)
finalList.append(sub2)
return finalList
For working on the two lists simultaneously you can use zip() Docs Here
For example:
for value in zip(list1, list2):
print (value[0], value[1])
will return:
['A', 14, 'I', 10, 20] ['A', 14, 'Y', 0, 200]
['B', 15, 'S', 30, 40] ['B', 15, 'M', 0, 400]
['C', 16, 'F', 50, 60] ['C', 17, 'G', 0, 600]
so using zip you can work on both your lists at the same time.
Here's one approach that converts the lists into a dict, and takes advantage of the fact that overlapping items from list2 will just overwrite their list1 counterparts:
combined_list = list1 + list2
final_dict = {tuple(i[:2]):tuple(i[2:]) for i in combined_list}
> {('A', 14): ('Y', 0, 200),
('B', 15): ('M', 0, 400),
('C', 16): ('F', 50, 60),
('C', 17): ('G', 0, 600)}
merged_list = [list(k) + list (final_dict[k]) for k in final_dict]
> [['C', 16, 'F', 50, 60],
['B', 15, 'M', 0, 400],
['C', 17, 'G', 0, 600],
['A', 14, 'Y', 0, 200]]
If the ordering of the list is important, you can just sort at the end or use an OrderedDict to create the merge in the first place.
Here's one way to do it using a list comprehension:
lst = [i for x, y in zip(list1, list2)
for i in (([*x[:2], y[2], x[3], y[4]],) if x[1] == y[1] else (x, y))]
print(lst)
# [['A', 14, 'Y', 10, 200], ['B', 15, 'M', 30, 400], ['C', 16, 'F', 50, 60], ['C', 17, 'G', 0, 600]]
The construction of the inner list for the matching case makes it slightly unreadable. It would be much readable in a 'deflattened' form with a for loop:
def merge_lists(list1, list2):
lst = []
for x, y in zip(list1, list2):
if x[1] == y[1]:
lst.append([*x[:2], y[2], x[3], y[4]])
else:
lst.extend((x, y))
return lst
Your "join" algorithm can work on each item independently and is straightforward:
def join_list(item1, item2):
if item1[1] == item2[1]:
result = item1[:]
result[2] = item2[2]
result[4] = item2[4]
return (result,)
return item1[:], item2[:]
This function always returns tuples: singletons in the cas of equality or couples in the general case.
You can apply this function to your two lists list1 and list2, using map() function. But the result will be a list of tuples (in fact a generator in Python 3), so you need to flatten the result:
list1 = [['A', 14, 'I', 10, 20], ['B', 15, 'S', 30, 40], ['C', 16, 'F', 50, 60]]
list2 = [['A', 14, 'Y', 0, 200], ['B', 15, 'M', 0, 400], ['C', 17, 'G', 0, 600]]
joined = [x
for row in map(join_list, list1, list2)
for x in row]
print(joined)
You get what you expect.

Organize list of lists in Python

Let's say a have a list of lists in Python:
list_of_values = [[a, b, c], [d, e, f], [g, h, i], [j, k, l]]
And I want to convert automatically to independent lists like:
list1 = [[a, b, c],[d + g + j, e + h + k, f + i + l]]
list2 = [[d, e, f], [g + j, h + k, i + l]]
list3 = [[g, h, i], [j, k, l]]
Let's say I have a list of lists of integers in Python:
list_of_values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
And I want to convert automatically to independent lists like:
list1 = [[1, 2, 3],[4 + 7 + 10, 5 + 8 + 11, 6 + 9 + l2]]
list2 = [[4, 5, 6], [7 + 10, 8 + 11, 9 + 12]]
list3 = [[7, 8, 9], [10, 11, l2]]
Performing the math:
list1 = [[1, 2, 3], [21, 24, 27]]
list2 = [[4, 5, 6], [17, 19, 21]]
list3 = [[7, 8, 9], [10, 11, l2]]
For your updated Question:
Suppose you have "list of lists of strings" like below:
s = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
Then you can use: join to concatenate:
>>> for i in range(len(s)):
... [s[i], map(lambda t: ''.join(t), zip(*s[i + 1:]))]
...
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
[['j', 'k', 'l'], []]
If you don't need last line in output then just use range argument less then one of length:
>>> for i in range(len(s)-1):
... [s[i], map(''.join, zip(*s[i + 1:]))] # remove lambda function
...
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
But suppose if you have "list of lists of numbers" e.g.:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Then you can use sum function:
>>> for i in range(len(l) - 1):
... [l[i], map(sum, zip(*l[i + 1:]))]
...
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]
Edit:..
If you wants to make single function for both strings and number then you canmake use of add() operator from operator library.
Check add() function:
>>> from operator import add
>>> add(1, 2)
3
>>> add('1', '2') # this is like + works
'12'
Now, using it make a new my_add() that add all elements in a sequence, check following codes:
>>> def my_add(t):
... return reduce(add, t)
...
>>> my_add(('a', 'b'))
'ab'
>>> my_add((2, 1))
3
Now, write a function using my_add() function that will so your work:
def do_my_work(s):
for i in range(len(s)-1):
print [s[i], map(my_add, zip(*s[i + 1:]))]
Now, see how this works for you:
>>> s
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
>>> do_my_work(s)
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
>>> l
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> do_my_work(l) # so same function for str and int both!
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]
>>> import itertools
>>> lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
>>> for i, item in enumerate(lst):
print [item, itertools.chain.from_iterable(lst[i+1:])]
[['a', 'b', 'c'], ['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']]
[['d', 'e', 'f'], ['g', 'h', 'i', 'j', 'k', 'l']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
[['j', 'k', 'l'], []]
for i in range(len(list_of_values) - 1):
print [list_of_values[i]] + [map(list, zip(*list_of_values[i+1:]))]
Output
[['a', 'b', 'c'], [['d', 'g', 'j'], ['e', 'h', 'k'], ['f', 'i', 'l']]]
[['d', 'e', 'f'], [['g', 'j'], ['h', 'k'], ['i', 'l']]]
[['g', 'h', 'i'], [['j'], ['k'], ['l']]]
For the numbers, you can simply do
list_of_values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
for i in range(len(list_of_values) - 1):
print [list_of_values[i]] + [map(sum, zip(*list_of_values[i+1:]))]
Output
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]

Categories

Resources