【问题标题】:Returning Dictionary-length of words in string [duplicate]返回字符串中单词的字典长度[重复]
【发布时间】:2016-06-29 10:01:01
【问题描述】:

我需要构建一个将字符串作为输入并返回字典的函数。
键是数字,值是包含唯一单词的列表,这些单词的字母数等于键。
比如输入函数如下:

n_letter_dictionary("The way you see people is the way you treat them and the Way you treat them is what they become")

函数应该返回:

{2: ['is'], 3: ['and', 'see', 'the', 'way', 'you'], 4: ['them', 'they', 'what'], 5: ['treat'], 6: ['become', 'people']}

我写的代码如下:

def n_letter_dictionary(my_string):
    my_string=my_string.lower().split()
    sample_dictionary={}
    for word in my_string:
        words=len(word)
        sample_dictionary[words]=word
    print(sample_dictionary)
    return sample_dictionary

函数返回字典如下:

{2: 'is', 3: 'you', 4: 'they', 5: 'treat', 6: 'become'}

字典不包含具有相同数量字母的所有单词,而是仅返回字符串中的最后一个。

【问题讨论】:

    标签: python string dictionary


    【解决方案1】:

    由于您只想在lists 中存储唯一值,因此使用set 实际上更有意义。你的代码几乎是正确的,你只需要确保你创建一个set 如果words 不是你字典中的一个键,但是你添加到set 如果words 已经是一个键在你的字典里。以下显示:

    def n_letter_dictionary(my_string):
        my_string=my_string.lower().split()
        sample_dictionary={}
        for word in my_string:
            words=len(word)
            if words in sample_dictionary:
                sample_dictionary[words].add(word)
            else:
                sample_dictionary[words] = {word}
        print(sample_dictionary)
        return sample_dictionary
    
    n_letter_dictionary("The way you see people is the way you treat them and the Way you treat them is what they become")
    

    输出

    {2: set(['is']), 3: set(['and', 'the', 'see', 'you', 'way']), 
     4: set(['them', 'what', 'they']), 5: set(['treat']), 6: set(['become', 'people'])}
    

    【讨论】:

    • 哦,这样更好,我们的其他解决方案会引发 KeyError...
    • 如何对列表进行排序 ['the', 'way', 'you', 'see', 'the', 'way', 'you', 'and', 'the', '方式','你']
    • 如果你想按字母顺序做some_list.sort()
    【解决方案2】:

    您的代码的问题在于您只是将最新的单词放入字典中。相反,您必须将该单词添加到一些具有相同长度的单词集合中。在您的示例中,这是一个list,但假设顺序不重要,set 似乎更合适。

    def n_letter_dictionary(my_string):
        my_string=my_string.lower().split()
        sample_dictionary={}
        for word in my_string:
            if len(word) not in sample_dictionary:
                sample_dictionary[len(word)] = set()
            sample_dictionary[len(word)].add(word)
        return sample_dictionary
    

    您可以使用collections.defaultdict(set) 将其缩短一点:

        my_string=my_string.lower().split()
        sample_dictionary=collections.defaultdict(set)
        for word in my_string:
            sample_dictionary[len(word)].add(word)
        return dict(sample_dictionary)
    

    或使用itertools.groupby,但为此您必须先按长度排序:

        words_sorted = sorted(my_string.lower().split(), key=len)
        return {k: set(g) for k, g in itertools.groupby(words_sorted, key=len)}
    

    示例(三种实现的结果相同):

    >>> n_letter_dictionary("The way you see people is the way you treat them and the Way you treat them is what they become")
    {2: {'is'}, 3: {'way', 'the', 'you', 'see', 'and'}, 4: {'what', 'them', 'they'}, 5: {'treat'}, 6: {'become', 'people'}}
    

    【讨论】:

    • 完全正确,当然删除重复更有意义!
    【解决方案3】:

    使用sample_dictionary[words]=word,您将覆盖您目前放在那里的当前内容。您需要一个列表,并且可以附加到列表中。

    你需要的是:

    if words in sample_dictionary.keys():
        sample_dictionary[words].append(word)
    else:
        sample_dictionary[words]=[word]
    

    因此,如果此键有值,我将附加到它,否则创建一个新列表。

    【讨论】:

    • 是的,您实际上并不需要.keys()
    • 您好,非常感谢您的帮助。尽管如此,我仍然得到字典中已经存在的键的重复值。你知道不使用 set() 来防止重复单词的方法吗?
    • 为什么不想使用 set()?嗯,当然有办法。将else: 替换为elif word not in sample_dictionary[words]: -- 然后它将检查此条件
    【解决方案4】:

    您可以使用collections 库中的defaultdict。您可以使用它为字典的值部分创建默认类型,在本例中为列表,然后根据单词的长度附加到它。

    from collections import defaultdict
    
    def n_letter_dictionary(my_string):
        my_dict = defaultdict(list)
        for word in my_string.split():
            my_dict[len(word)].append(word)
    
        return my_dict
    

    您仍然可以在没有默认字典的情况下执行此操作,但长度会长一些。

    def n_letter_dictionary(my_string):
        my_dict = {}
        for word in my_string.split():
            word_length = len(word)
            if word_length in my_dict:
                my_dict[word_length].append(word)
            else:
                my_dict[word_length] = [word]
    
        return my_dict
    

    为了确保值列表中没有重复,不使用set()。但是请注意,如果您的值列表很大,并且您的输入数据相当独特,您将遇到性能挫折,因为检查列表中是否已经存在的值只会在遇到它时提前退出。

    from collections import defaultdict
    
    def n_letter_dictionary(my_string):
        my_dict = defaultdict(list)
        for word in my_string.split():
            if word not in my_dict[len(word)]:
                my_dict[len(word)].append(word)
    
        return my_dict
    
    # without defaultdicts
    def n_letter_dictionary(my_string):
        my_dict = {}                                  # Init an empty dict
        for word in my_string.split():                # Split the string and iterate over it
            word_length = len(word)                   # Get the length, also the key
            if word_length in my_dict:                # Check if the length is in the dict
                if word not in my_dict[word_length]:  # If the length exists as a key, but the word doesn't exist in the value list
                    my_dict[word_length].append(word) # Add the word
            else:
                my_dict[word_length] = [word]         # The length/key doesn't exist, so you can safely add it without checking for its existence
    

    因此,如果您有很高的重复频率并且要扫描的单词列表很短,那么这种方法是可以接受的。例如,如果您有一个随机生成的单词列表,其中仅包含字母字符的排列,导致值列表膨胀,那么扫描它们会变得很昂贵。

    【讨论】:

    • 非常感谢,我仍然得到字典中已经存在的键的重复值。有没有办法不使用 set() 删除重复的单词?
    • 我添加了一个关于在不使用set()的情况下确保没有重复的部分。
    • 我正在尝试使用您的第一种方法而不使用默认字典,方法是在“for word in my_string.split():”之后添加一个“if word not in my_dict”,但我仍然得到重复单词的相同输出。你能帮我解决没有默认字典的方法吗?
    • 我添加了一个不使用defaultdict 的示例,但列表中的结果是唯一的,但不使用set()。如果你有if word not in my_dict,那将始终返回True,因为word 在值中,并且你的语句只检查my_dict 的键。
    【解决方案5】:

    我想出的最短解决方案使用defaultdict

    from collections import defaultdict
    
    sentence = ("The way you see people is the way you treat them"
                " and the Way you treat them is what they become")
    

    现在算法:

    wordsOfLength = defaultdict(list)
    for word in sentence.split():
        wordsOfLength[len(word)].append(word)
    

    现在wordsOfLength 将保存所需的字典。

    【讨论】:

      【解决方案6】:

      itertools groupby 是完美的工具。

      from itertools import groupby
      def n_letter_dictionary(string):
          result = {}
          for key, group in groupby(sorted(string.split(), key = lambda x: len(x)), lambda x: len(x)):
              result[key] = list(group)
          return result
      

      print n_letter_dictionary("你看人的方式就是你对待他们的方式,你对待他们的方式就是他们变成的样子")

      # {2: ['is', 'is'], 3: ['The', 'way', 'you', 'see', 'the', 'way', 'you', 'and', 'the', 'Way', 'you'], 4: ['them', 'them', 'what', 'they'], 5: ['treat', 'treat'], 6: ['people', 'become']}
      

      【讨论】:

      • 确实,让我尽快纠正。
      • 另外,key = lambda x: len(x)key=len 相同;-)
      • 是的,注意到了,谢谢!
      • 为了取悦groupby,对事物进行分类是不必要的。重新考虑这方面。
      【解决方案7】:
      my_string="a aa bb ccc a bb".lower().split()
      sample_dictionary={}
      for word in my_string:
          words=len(word)
          if words not in sample_dictionary:
              sample_dictionary[words] = []
          sample_dictionary[words].append(word)
      print(sample_dictionary)
      

      【讨论】:

      • 重新考虑变量 words 的名称。它是wordLength 或类似的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-04
      • 2021-05-19
      • 2017-08-19
      • 2020-07-12
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多