【问题标题】:Sort and iterate over the first letters of a large list对大列表的第一个字母进行排序和迭代
【发布时间】:2021-03-19 17:27:21
【问题描述】:

我有一个 input 字符串列表,这些字符串由逗号分隔,如下所示:

list_to_split = ['flyer, black and white', 'flyer, blue', 'fly-swatter, black', 'helmet, heavy',
'armlet, silver and gold', 'cherry, black', 'violin, very old', 'concrete, grey']

我想遍历以相同字母开头的项目,并用它们更新一个空字典,以获得如下所示的所需输出

letter_ordered_dict = {'a': ['armet'], 'c': ['cherry', 'concrete'], 'f': ['flyer', 'fly-swatter'],
'h': ['helmet'], 'v': ['violin']}

首先,我尝试这样做的方式显然是首先通过理解获取原始列表的第一个元素:

list_split_by_first_element = [first_elm.split(',')[0] for elm in list_that_has_been_ordered]
list_split_by_first_element.sort()

这会产生输出:

['armlet', 'cherry', 'concrete', 'flyer', 'flyer', 'fly-swatter', 'helmet', 'violin']

我坚持的部分是如何按这些元素的第一个字母分组并跳过重复项以生成上面的输出。

有更好的方法吗?

【问题讨论】:

  • 是的,可能是最好的。在循环内部,我可以通过字符串本身的第一个元素进一步拆分字符串元素,将其链接到字典键,并在内部附加到值列表。
  • 我不知道你在想什么组——我只是觉得你写的东西完全是愚蠢的,因为你没有尝试自己做或找到一个(太常见了没有在这里提出问题)。您应该发送honest attempt at the solution,然后然后询问有关它的具体问题(如有必要)。
  • 您需要在每个字母条目中对项目进行排序吗?或者任何订单都可以吗?如果每个字母列表中的项目可能是乱序的,那么使用 set() 类型有相对简单/快速的重复删除方法。如果应该对它们进行排序,那就有点棘手了。

标签: python python-3.x list dictionary grouping


【解决方案1】:

这应该可以完成工作:

import itertools
tmp = sorted(e.split(',')[0] for e in list_to_split) # list_split_by_first_element
letter_ordered_dict = {k:list(set(v)) for k,v in itertools.groupby(tmp, lambda item: item[0])}

letter_ordered_dict中输出结果:

{'a': ['armlet'],
 'c': ['concrete', 'cherry'],
 'f': ['fly-swatter', 'flyer'],
 'h': ['helmet'],
 'v': ['violin']}

【讨论】:

  • 我喜欢 Python 单行代码的强大功能! (tmp 变量只是一个可读性重构)做得很好。
【解决方案2】:

对于这种扫描/聚合问题,您通常需要循环而不是列表推导。假设 list_split_by_first_element 已排序,这应该可以工作:

letter_ordered_dict = dict()
prev_word = ''
for word in list_split_by_first_element:
    if word == prev_word:
        # skip repeated words
        continue
    letter = word[0]
    letter_ordered_dict.setdefault(letter, []).append(word)

请注意,dict.setdefault 要么查找密钥,要么将其设置为指定的值(如果它不存在),这正是您想要的。

如果列表很长或有很多重复的单词,您可能会发现对子列表进行排序比对完整列表进行排序更快。那么这样的事情可能会起作用:

list_to_split = ['flyer, black and white', 'flyer, blue', 'fly-swatter, black', 'helmet, heavy',
'armlet, silver and gold', 'cherry, black', 'violin, very old', 'concrete, grey']

set_dict = dict()
for phrase in list_to_split:
    word, rest = phrase.split(',', 1)
    set_dict.setdefault(word[0], set()).add(word)
letter_ordered_dict = {
    letter: sorted(words)
    for letter, words in set_dict.items()
}

如果不需要对每个字母的子列表进行内部排序,则可以通过在第二个示例中将 sorted 替换为 list 来节省一些时间。

【讨论】:

  • 我喜欢这个解决方案,因为我总是喜欢更长一点但更明显的输入和输出。我还添加了某些没有逗号可拆分的边缘情况。谢谢你!
【解决方案3】:

所以我在得到list_of_words之后就开始写代码了

list_of_words = ['armlet', 'cherry', 'concrete', 'flyer', 'flyer', 'fly-swatter', 'helmet', 'violin']

list_of_words = list(set(list_of_words))

first_char_dict = dict()

for word in list_of_words:
    if word[0] in first_char_dict:
        first_char_dict[word[0]].append(word)
    else:
        first_char_dict[word[0]] = [word]
        
print(first_char_dict)

输出:{'h': ['helmet'], 'v': ['violin'], 'f': ['fly-swatter', 'flyer'], 'c': ['cherry', 'concrete'], 'a': ['armlet']}

虽然我想提醒您注意,您在拆分字符串时只选择了一个世界。这是你需要的吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2021-04-04
    • 1970-01-01
    • 2022-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多