简体   繁体   中英

How do I represent a dictionary from a list assuming that every other number by its side is its value?

I have a list that looks like this,

lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']

In this list, each number after the word represents the value of the word. I want to represent this list in a dictionary such that the value of each repeated word gets added. I want the dictionary to be like this:

dict = {'hello':'2', 'go':'14', 'sit':'6','line':'3','play':'0'}

In the list 'go' occurs twice with two different values so we add the number that occur just after the word, similarly for other words. This is my approach, it does not seem to work.

import csv
with open('teest.txt', 'rb') as input:
    count = {}
    my_file = input.read()
    listt = my_file.split()
    i = i + 2
    for i in range(len(listt)-1):
        if listt[i] in count:
            count[listt[i]] = count[listt[i]] + listt[i+1]
        else:
            count[listt[i]] = listt[i+1]

Counting occurrences of unique keys is usually possible with defaultdict .

import collections as ct 

lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']
dd = ct.defaultdict(int)
iterable = iter(lista)

for word in iterable:
    dd[word] += int(next(iterable)) 

dd
# defaultdict(int, {'go': 14, 'hello': 2, 'line': 3, 'play': 0, 'sit': 6})

Here we initialize the defaultdict to accept integers. We make a list iterator, both creates a generator and allows us to call next() on it. Since the word and value occur in consecutive pairs in the list, we will iterate and immediately call next() to extract these values in sync. We assign these items as (key, value) pairs to the defaultdict , which happens to keep count.

Convert the integers to strings if this is required:

{k: str(v) for k, v in dd.items()}
# {'go': '14', 'hello': '2', 'line': '3', 'play': '0', 'sit': '6'}

An alternate tool may be the Counter (see @DexJ's answer), which is related to this type of defaultdict . In fact, Counter() can substitute defaultdict(int) here and return the same result.

You can "stride" the array 2 items at a time using a range() . The optional 3rd argument in a range lets you define a "skip".

range(start, stop[, step])

Using this, we can create a range of indexes that skip ahead 2 at a time, for the entire length of your list. We can then ask the list what "name" is at that index lista[i] and what "value" is after it lista[i + 1] .

new_dict = {}
for i in range(0, len(lista), 2):
    name = lista[i]
    value = lista[i + 1]

    # the name already exists
    # convert their values to numbers, add them, then convert back to a string
    if name in new_dict:
        new_dict[name] = str( int(new_dict[name]) + int(value) )
    # the name doesn't exist
    # simply append it with the value
    else:
        new_dict[name] = value

as explained by @Soviut you may use range() function with step value 2 to reach to word directly. as I seen in your list you have value stored as string so I have converted them to integers.

lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']
data = {}
for i in range(0, len(lista), 2): # increase searching with step of 2 from 0 i.e. 0,2,4,...
    if lista[i] in data.keys(): # this condition checks whether your element exist in dictionary key or not
        data[lista[i]] = int(data[lista[i]]) + int(lista[i+1])
    else:
        data[lista[i]] = int(lista[i+1])
print(data)

Output

{'hello': 2, 'go': 14, 'sit': 6, 'line': 3, 'play': 0}

Another solution using iter() , itertools.zip_longest() and itertools.groupby() functions:

import itertools

lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']
it = iter(lista)
d = {k: sum(int(_[1]) for _ in g)
        for k,g in itertools.groupby(sorted(itertools.zip_longest(it, it)), key=lambda x: x[0])}
print(d)

The output:

{'line': 3, 'sit': 6, 'hello': 2, 'play': 0, 'go': 14}
lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']
dictionary = {}

for keyword, value in zip(*[iter(lista)]*2): # iterate two at a time
    if keyword in dictionary: # if the key is present, add to the existing sum
        dictionary[keyword] = dictionary[keyword] + int(value)
    else: # if not present, set the value for the first time
        dictionary[keyword] = int(value)

print(dictionary)

Output:

{'hello': 2, 'go': 14, 'sit': 6, 'line': 3, 'play': 0}

You can use range(start,end,steps) to get endpoint and split list and just use Counter() from collections to sum duplicate key's value and you're done :)

here yourdict will be {'go': 14, 'line': 3, 'sit': 6, 'play': 0, 'hello': 2}

from collections import Counter
counter_obj = Counter()

lista = ['hello','2','go','5','sit','4','line','3','sit','2', 'go','9','play','0']
items, start = [], 0

for end in range(2,len(lista)+2,2):
    print end
    items.append(lista[start:end])
    start = end

for item in items:
    counter_obj[item[0]] += int(item[1])

yourdict = dict(counter_obj)
print yourdict

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM