Home > Net >  Sum list of list by first index
Sum list of list by first index

Time:07-31

I want to "sum" two lists of lists by first index.

To give an example, I have L1 and L2:

L1=[[2,"word1"],[1,"word2"],[3,"word3"]]
L2=[[7,"word4"],[6,"word1"],[3,"word5"],[6,"word3"]]

and I want this as output:

L3=[[8,"word1"],[1,"word2"],[9,"word3"],[7,"word4"],[3,"word5"]]

Of course I know how to code this but not in a very elegant way, with some while loop, and I'm wondering if there is no simpler solution...

My code so far:

def sum_list(L1,L2):
  word1=[x[1] for x in L1]
  word2=[x[1] for x in L2]
  score1=[x[0] for x in L1]
  score2=[x[0] for x in L2]
  word3=[]
  L3=[]
  i=0
  while i<len(word1):
    word3.append(word1[i])
    if word1[i] not in word2:
      L3.append([score1[i],word1[i]])
    else:
      L3.append([score1[i] score2[word2.index(word1[i])],word1[i]])
    i=i 1
  i=0
  while i<len(word2):
    if word2[i] not in word3:
      L3.append([score2[i],word2[i]])
    i=i 1
  return L3

Thanks

CodePudding user response:

You could use a Counter for that.:

from collections import Counter


L1 = [[2, "word1"], [1, "word2"], [3, "word3"]]
L2 = [[7, "word4"], [6, "word1"], [3, "word5"], [6, "word3"]]

L1_reversed = [l[::-1] for l in L1]
L2_reversed = [l[::-1] for l in L2]

L1_counter = Counter(dict(L1_reversed))
L2_counter = Counter(dict(L2_reversed))
L3_counter = L1_counter   L2_counter
print(L3_counter)

Gives:

Counter({'word3': 9, 'word1': 8, 'word4': 7, 'word5': 3, 'word2': 1})

And if you want to have your list of lists back:

L3 = [[value, key] for key, value in L3_counter.items()]
print(L3)

Which gives:

[[8, 'word1'], [1, 'word2'], [9, 'word3'], [7, 'word4'], [3, 'word5']]

The code is a bit convoluted, to change the data in the needed structure. But maybe you'd want to rethink about how you keep the data anyways as a list of list is not necessarily the best structure to represent such data. A dict would be the better representation here (no duplicates, and directly indexable by key).

CodePudding user response:

    # Accumulate counts in a dict.
    d = dict()
    list(map(lambda p: d.__setitem__(p[1],d.setdefault(p[1], 0) p[0]), L1))
    list(map(lambda p: d.__setitem__(p[1],d.setdefault(p[1], 0) p[0]), L2))
    # Unpack the dict.
    L3 = [[k, v] for k,v in d.items()]
    print(L3)

A more verbose approach:

def accumulateInDict(d, l):
    for pair in l:
        key = pair[1]
        count = d.get(key, 0)
        d[key] = count   pair[0]
        
# Accumulate counts in a dict.
d = dict()
accumulateInDict(d, L1)
accumulateInDict(d, L2)
# Unpack the dict.
L3 = [[k, v] for k,v in d.items()]
print(L3)
  • Related