Vigneshwaran Thenraj
Vigneshwaran Thenraj

Reputation: 708

Summation in python dictionary

How to create a dictionary in python by using for loop

CPO     1
CL      1
SL      1
EL      1
CPO     1
SL      1
CPO     1

So the expected result should be as follow {'CPO':3,'CL':1,'SL':2,'EL':1}

I tried this:

avail = defaultdict(list)
    cpo = cl = sl= el = 0
    for i in hr_line_id:
        if i.leave_code == 'CPO':
            cpo = cpo + i.no_of_days
            avail['cpo'].append(cpo)
        elif i.leave_code == 'CL':
            cl = cl + i.no_of_days
            avail['cl'].append(cl)
        elif i.leave_code == 'SL':
            sl = sl + i.no_of_days
            avail['sl'].append(sl)
    print avail

Upvotes: 2

Views: 100

Answers (5)

chthonicdaemon
chthonicdaemon

Reputation: 19820

How about this slightly shorter version with Counter?

from collections import Counter

counts = Counter((i.leave_code.lower(), i.no_of_days) for i in hr_line_id)

Upvotes: 1

ryachza
ryachza

Reputation: 4540

I'd second the use of collections.Counter in the comments, but to adjust your current code, something like this should work:

avail = defaultdict(lambda: 0)
for i in hr_line_id:
    if i.leave_code == 'CPO':
        avail['cpo'] += i.no_of_days
    elif i.leave_code == 'CL':
        avail['cl'] += i.no_of_days
    elif i.leave_code == 'SL':
        avail['sl'] += i.no_of_days
print avail

Per the comments, the if chain here is adding a lot of noise. Assuming the target key isn't a function of the input (like .lower()) and/or you only want to allow a certain set of keys, something like this would probably be preferred:

avail = defaultdict(lambda: 0)
keyMapping = {
  'CPO': 'cpo',
  'CL' : 'cl',
  'SL' : 'sl'
}
for i in hr_line_id:
  if i.leave_code in keyMapping:
    avail[keyMapping[i.leave_code]] += i.no_of_days
  else:
    pass # handle unexpected key
print avail

Upvotes: 4

Eric Duminil
Eric Duminil

Reputation: 54293

As mentioned by @JeanFrancoisFabre, this is the perfect example for collections.Counter:

from collections import Counter

text = """CPO     1
CL      1
SL      1
EL      1
CPO     1
SL      1
CPO     1"""

count = Counter()

for line in text.split("\n"):
    k,v = line.split()
    count[k] += int(v)

print(count)
Counter({'CPO': 3, 'SL': 2, 'CL': 1, 'EL': 1})

If you want lowercase keys, you could use count[k.lower()] += int(v):

Counter({'cpo': 3, 'sl': 2, 'cl': 1, 'el': 1})

If the quantity is always 1, you could simply write a one-liner:

Counter(line.split()[0] for line in text.split("\n"))
# Counter({'CPO': 3, 'SL': 2, 'CL': 1, 'EL': 1})

Upvotes: 5

utengr
utengr

Reputation: 3355

Here is another way to do it using loop:

text = """CPO     1
CL      1
SL      1
EL      1
CPO     1
SL      1
CPO     1"""

text_split = text.split() # split the text [CPO, 1, CL, 1 and so on]
dict_k = text_split[0::2] # values at odd index
dict_v = text_split[1::2] # values at even index

dict_t = {}

for k, v in zip(dict_k, dict_v):
    dict_t[k] = dict_t.get(k, 0) + int(v)

print(dict_t)

# output:{'SL': 2, 'CPO': 3, 'EL': 1, 'CL': 1}

Upvotes: 1

How about nope
How about nope

Reputation: 770

Except counter you can simply loop.

avail = {}
for i in hr_line_id:
    if i.leave_code in avail:
        avail[i.leave_code] += i.no_of_days
    else
        avail[i.leave_code] = i.no_of_days

Upvotes: 0

Related Questions