【问题标题】:Creating a dictionary from list of lists using only one for loop仅使用一个 for 循环从列表列表创建字典
【发布时间】:2020-07-03 13:02:14
【问题描述】:

我在测试中遇到了这个问题。这个问题有两个部分:

第一部分:

给定一个口味列表,例如。 ['A','A','A','A','B','B','B','B','B','C','C','C',' C'],编写一个函数,分别返回每个风味的个数的字典。

我的解决方案:

flavors = ['A','A','A','A','B','B','B','B','B','C','C','C','C']

def count_flavors(l):
    dict_flavors={}
    for i in l:
        dict_flavors[i] = l.count(i)
    return dict_flavors

print(count_flavors(flavors))

第二部分:

使用不超过一个 for 循环编写一个函数,该函数接受一系列风味列表,例如。 [['A', 'A', 'B', 'B', 'B', 'C', 'C'], ['A', 'A', 'B', 'B', 'B ', 'B', 'C'], ['A', 'B', 'C', 'C']] 并返回每个风味总数的字典。您必须在此解决方案中包含您在第一部分中定义的函数。 (澄清一下,本质上应该只有两个 for 循环;一个来自第一部分,一个来自第二部分)

到目前为止,我的解决方案如下:

batches = [['A','A','A','A','B','B','B','B','B','C','C','C','C'], ['A', 'A', 'B', 'B' ,'B','B','C'], ['A','B','C','C']]

def batch_count(b):
    batch_dict = []
    result = {}
    for j in b:
        batch_dict.append(count_flavors(j))
    print(batch_dict)
    for i in batch_dict:
        for k in i.keys():
            result[k] = result.get(k,0) + i[k]
    return result

print('batch count 1:' + str(batch_count(batches)))

我正在努力寻找一个只为此部分使用一个 for 循环的解决方案。我知道有类似collections.Counter() 这样的模块存在。是否有一个不包含任何可能解决此问题的模块的天真的解决方案?

谢谢!

【问题讨论】:

  • 嘿,我已根据您的要求更新了我的答案。让我知道它对你有什么好处:)

标签: python-3.x list dictionary for-loop nested-lists


【解决方案1】:

这里是最好的天真解决方案我能想到的为了实现你想要的

使用该解决方案的好处

  1. 无需创建像 batch_dict = [] 这样的额外变量,这会占用系统中不必要的空间
  2. 无需使用不同的方法进行多次计算,就像您在上面使用count_flavors() 所做的那样
  3. 简单明了,易于理解

最终解决方案

batches = [['A','A','A','A','B','B','B','B','B','C','C','C','C'], ['A', 'A', 'B', 'B' ,'B','B','C'], ['A','B','C','C']]

def batch_count(b):
    result = {} # for storing final count results
    # two loops are required to get into the arrays of array, not other option is there
    for items in b:
        # Getting the nested array item here
        for item in items:
            # final computation, if the item is there in the result dict, then increment
            # else simply assign 1 to the item as a key which eventually gives you the total number
            # of counts of each item throughout the batches array items
            if item in result:
                result[item] += 1
            else:
                result[item] = 1
    return result

print('batch count 1:' + str(batch_count(batches)))

# OUTPUT
# >>> batch count 1:{'A': 7, 'C': 7, 'B': 10}

您也可以随意对其他批次进行测试,并告诉我。到目前为止,这是一种天真的解决方案,可以给出您想要实现的目标。继续学习:)

另一种解决方案 [使用第一种方法 COUNT_FLAVORS]

嘿,如果你真的想使用第一种方法,那么有一个变通办法,但你现在需要妥协一件事,那就是必须导入 Counter,但我向你保证,它将是就这么简单,会给你直接的答案

您的count_flavors 工作正常,所以我们按原样使用count_falvors()。 我们现在将对batch_count 方法进行更改

最终解决方案

from collections import Counter

# Taking your method as is, to get the dictionary which counts
# the items occurence from your array
def count_flavors(l):
    dict_flavors={}
    for i in l:
        dict_flavors[i] = l.count(i)
    return dict_flavors


# This method will do your stuffs
def batch_count(b):
   result = {} #this will be used to return the final result
   # now just one loop, since we will passing the array 
   # to our method for computation count_flavors()
   for items in b:  # this will give out single array
        '''
        now we will call your count_flavor method
        we will use Counter() to merge the dictionary data
        coming from the count_flavor and then add it to the result
        Counter() keep track of same item, if present in multiple
        dict, ADDS +1 to the same item, doesn't duplicate value
        Hence counter required
        '''
        if len(result) != 0:
            # if the result is not empty, then result = result + data
            result += Counter(count_flavors(items)) # no more extra for loop
        else:
            # else first fill the data by assigning it
            result = Counter(count_flavors(items))
   # this will give out the output in {}
   # else the output will come in Counter({}) format
   return dict(result)
   
# our test array of arrays
batches = [['A','A','A','A','B','B','B','B','B','C','C','C','C'], ['A', 'A', 'B', 'B' ,'B','B','C'], ['A','B','C','C']]

print('batch count 1:' + str(batch_count(batches)))

# OUTPUT
# >>> batch count 1:{'A': 7, 'B': 10, 'C': 7}

通过这种方式,您也可以使用count_flavors() 方法实现输出,在batch_count() 中也没有多个循环。希望这会让你更清楚:)。如果这对你有用,你可以接受这个答案,对于那些来寻找这个问题的答案的人:)

【讨论】:

  • 感谢您的回复!我同意这是一个更直接的解决方案,并且必须有多个“for”循环。为了这个问题,我仍在寻找如何修改您的解决方案,以使其满足使用第 i 部分定义的功能的要求......尽管如此,还是感谢您的输入! :)
  • 嘿@kwekie,没问题。我已经更新了我的答案,并且在更新后的答案中,ANOTHER SOLUTION [MAKING USE OF FIRST METHOD COUNT_FLAVORS],我们使用了您想要的方法,没有额外的循环。让我知道这是否适合你:)
  • 嘿 @Alok 我不知道 Counter 对象可以使用 += 相互添加,我正在寻找一种方法来实现两个 dict 对象的 += 方法,但操作是不受支持...我想您的最终解决方案似乎最接近问题要求,再次感谢! :D
  • 我真的很高兴,我们有机会互相学习:) 一切顺利
【解决方案2】:

通过以这种方式修改您的方法,第一个函数可以变得更快:

def count_flavors(lst):
    dict_flavors = {}
    for item in lst:
        if item in dict_flavors:
            dict_flavors[item] += 1
        else:
            dict_flavors[item] = 1
    return dict_flavors

您也可以使用Counter 来简化您的代码:

from collections import Counter

def count_flavors(lst):
    return dict(Counter(lst))

第二个函数可以使用itertools.chain

from collections import Counter
from itertools import chain

def batch_count(b):
    return dict(Counter(chain(*b)))

【讨论】:

  • 感谢您的回复!您能否解释一下为什么您对第 i 部分的解决方案会更快?谢谢
  • @kwekie 假设您有一个列表,其中相同的元素重复了 1000 次。在您的解决方案中,您 count 该元素 1000 次。换句话说,您扫描整个列表 1000 次。相反,你可以只做一次。使用 count 就像使用 for 循环遍历列表的所有元素。因此,在您的情况下,您将在另一个 for 循环中有一个 for 循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 2018-02-16
相关资源
最近更新 更多