1

I've a list of lists, and each inner list has three objects. I'd like to sum the 1st index (2nd object) of each sublist, but only if the other two objects in the sublists are the same. For example:

list_in = [['aa', 2, 'bb'], ['aa', 2, 'bb']]

Since 'aa' and 'bb' are the same, I'd like to add the 2 and 2 to equal 4, and output this into a new list:

list_out = ['aa', 4, 'bb']

So I need an if statement. I tried this with the following:

list_out = []
if i[0]==i[0] for i in list_in:
    total = [sum(list_in[1]) for i in range(len(list_in))]
    list_out.append(i[0], total, i[2])

But python gives me an InvalidSyntax error. I'm unsure how to fix this.

Then I tried to just construct a new list based on the condition that if the 1st and 3rd objects are the same, sum the 2nd objects:

list_out, total = [], 0
for i in list_in:  # "i" is a list within the "list_in" list.
    x, y, z = i[0], i[1], i[2]
    if x not in list_out and z not in list_out:
        list_out.append([x, y, z])
    elif x in list_out and z in list_out:
        total_y += y
        list_out.append([x, total_y, z])
return list_out

However, this just gives me the same list as I started with. Apparently the if and elif statements aren't working correctly.

2
  • Please clarify how many lists are expected in your list of lists, and how many you need to compare to produce how many sums? Commented Jan 30, 2018 at 21:26
  • @JohnH Sorry, I seemed to have missed this comment. I don't have an expected number of sublists, since I'm parsing a file. The number of sublists could be 2, but it could go up to 50 or more. I'd like to be able to produce one sum for every time the 1st object and 3rd object are the same. Commented Jan 30, 2018 at 21:46

2 Answers 2

4

You can use itertools.groupby:

import itertools
list_in = [['aa', 2, 'bb'], ['aa', 2, 'bb']]
new_list = [(a, list(b)) for a, b in itertools.groupby(sorted(list_in, key=lambda x:(x[0], x[-1])), key=lambda x:(x[0], x[-1]))]
final_data = [[a, sum(c[1] for c in d), b] for (a, b), d in new_list][0]

Output:

['aa', 4, 'bb']

itertools.groupby allows for a more generic solution should the length of list_in exceed two.

Edit: the solution will work for larger lists:

list_in = [['aa', 2, 'bb'], ['aa', 2, 'bb'], ['aa', 15, 'bb']]
new_list = [(a, list(b)) for a, b in itertools.groupby(sorted(list_in, key=lambda x:(x[0], x[-1])), key=lambda x:(x[0], x[-1]))]
final_data = [[a, sum(c[1] for c in d), b] for (a, b), d in new_list][0]

Output:

['aa', 19, 'bb']

In Python, a function is an object. A lambda function is known as an "anonymous function" because when its object is created, it is not bound to a name. Instead, the function object itself is returned.

Sign up to request clarification or add additional context in comments.

3 Comments

This appears to work. However, I'm a python newbie, so I've some questions: 1. Can you explain a little more about the code? What does "list(b)" mean? 2. I've seen lambda used a lot, and I've tried reading (and watching some YouTube videos) about it, but I'm still not understanding it fully. At best I've learned it's an "anonymous function". In the code here, what does lambda do? 3. Will this work for nested lists longer than 2 elements? E.g. list_in = [['aa', 2, 'bb'], ['aa', 2, 'bb']], ['aa', 15, 'bb], ...] Thank you!
Oops, I just read your last line, and see now that it answers my third questions. That's what I get for reading too quickly...
I see your edits, thanks. But this code doesn't yield the desired output if the element 'aa' and 'bb' for each sublist aren't the same. In this situation, I'd like the result to be an unchanged list; i.e. list_in = list_out. With your current code, I seem to just get 1 list output. I'd like to sum the 2nd object only if the 1st object and 3rd object are the same for a sublist. I looked at your code, and I tried to add this functionality with an if statement: if len(new_list) == 1 then execute the code under final_data. Is this the pythonic way to do this?
1

I think I am doing manually what Ajax1234 does with groupby, here it comes:

list_in = [['aa', 2, 'bb'], ['aa', 2, 'bb']]

grp = {}
for inner in list_in:
    key = (inner[0],inner[-1]) # tuple is immutable and can be key
    grp.setdefault(key,0)      # create key if needed with value 0
    grp[key]+=inner[1]         # add value

list_out = [[k[0],grp[k],k[1]] for k in grp]   # reassemble from dictionary

print(list_out)

Output:

[['aa', 4, 'bb']]

This will also include any sublist that has NO duplicate entry. Not sure if thats ok.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.