【问题标题】:How to map a list of strings to a list of integers [duplicate]如何将字符串列表映射到整数列表[重复]
【发布时间】:2020-11-14 20:36:41
【问题描述】:

我有一个包含 n 个元素的列表:

['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']

我必须为每个字符串分配一个数字,从零开始,如果元素不同,则加一,如果元素重复,则赋予相同的数字。示例:

['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
[ 0,    1,      1,      2,        0,     3,     4,     4,     5,       3    ]

我该怎么做?

【问题讨论】:

  • 请用您尝试过的代码更新您的问题。
  • 该代码没有正确缩进。目前还不清楚countcount2 应该是什么以及为什么它们有不同的类型。你能用普通话告诉我们吗?没有条件可以区分重复元素和非重复元素,因此预计此代码不起作用。此外,请提供minimal reproducible example,内联所有代码和示例数据。最后,作为这里的新用户,请使用tour 并阅读How to Ask
  • 你永远不会检查元素是否重复。
  • 我的建议是与您的老师或导师或同学坐下来,他们可以指导您正确的方向。我们给你答案会帮助你解决眼前的问题,但它不会教你如何思考和分解问题,这是编程的基本部分。你可能会在下一个作业问题中遇到类似的问题。随着课程的进行,课程作业还应建立在早期概念的基础上,因此如果您不自己解决早期的问题,那么后面的问题将比早期的问题困难得多。

标签: python


【解决方案1】:

使用辅助字典:

>>> [*map({k: v for v, k in enumerate(dict.fromkeys(final))}.get, final)]
[0, 1, 1, 2, 0, 3, 4, 4, 5, 3]

另一种方式:

>>> d = {}
>>> [d.setdefault(x, len(d)) for x in final]
[0, 1, 1, 2, 0, 3, 4, 4, 5, 3]

【讨论】:

  • @superb rain,谢谢你的第二个选项。这太棒了,它直接将值吐出到列表中,同时也分配给字典。
  • 如果有人刚接触编程,不知道如何处理问题中的问题,我非常怀疑他们是否能够理解这些复杂的单行语句。
【解决方案2】:

使用字典可以做到这一点。

def counts(a):
    dis = {}
    count=0
    for i in range(len(a)):
        if a[i] not in dis.keys():
            dis[a[i]] = count
            count+=1
        
    return([dis[x] for x in a])

【讨论】:

  • 嘿!一个实际给出请求结果的答案!
  • 我相信 for i, _ in enumerate(a)for i in range(len(a)) 更 Pythonic。但是您只在a[i] 中使用i,在这种情况下,只使用for x in a 并使用x 而不是a[i] 更有意义。
  • @BernhardBarker 同意
【解决方案3】:

使用defaultdict 并使用计数器作为默认值函数。

只要键存在,它就会返回存储的“第一次遇到的位置”,否则它会调用Incr.__call__,它会增加它的计数以提供一个新的第一次遇到的位置。

根据超级大脑的建议,使用现有的计数器类:

from collections import defaultdict 
from itertools import count

li = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
seen = defaultdict(count().__next__)
print( [seen[val] for val in li] )

像以前一样滚动我自己的 Incr,这确实给您带来了可以返回任何东西(例如 GUID)的优势:

from collections import defaultdict 

class Incr:
    def __init__(self):
        self.count = -1

    def __call__(self):
        self.count +=1 
        return self.count

li = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']

seen = defaultdict(Incr())

print( [seen[val] for val in li] )

两者都提供相同的输出:

[0, 1, 1, 2, 0, 3, 4, 4, 5, 3]

【讨论】:

  • 也可以使用itertools.count().__next__seen.__len__lambda: len(seen)作为默认工厂。
  • @superbrain itertools.count().__next__ 可能是一个不错的选择。说实话,我觉得你的 len(dict) 技巧令人印象深刻。但这有点聪明了,6个月后发生的事情还不够明显。但这肯定是个好主意。
【解决方案4】:

试试这个:

a = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
dct = {}
counter = 0
for i in range(len(a)):
    if a[i] not in dct.keys():
        dct[a[i]] = counter 
        counter += 1
print([(i, dct[i]) for i in a])

【讨论】:

  • 为什么要 +1?这不会产生 OP 要求的内容。
【解决方案5】:

你只需要证明你是否已经拥有它

def counts(final):
    count3 = [] # contains all objects that were already found
    count2=[]
    count=0
    for x in final:
        if x not in count3: # test if it's not already in count3
            count+=1
            count2.append(count)
            count3.append(x)
        else:
            count2.append(count)
    
return count2

【讨论】:

  • 您的解决方案为示例数据返回 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],而不是预期的输出。您永远不会向 count3 添加任何内容来测试您是否已经看到该元素。
  • 现在返回[1, 2, 3, 4, 5, 6]
  • 是的。为什么要对此 +1。人们只是将任何代码作为答案查看并说“当然,这很棒!”不阅读或尝试?
  • [1, 2, 2, 3, 3, 4, 5, 5, 6, 6] 我不会进一步测试您的代码。已经有正确的解决方案了。
  • 但是你为什么把它作为答案发布呢?这对任何人有什么帮助?
【解决方案6】:

最干净的方法可能是使用熊猫:

import pandas as pd
lst =  ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
pd.factorize(lst)

哪些输出:

(array([0, 1, 1, 2, 0, 3, 4, 4, 5, 3], dtype=int64),
 array(['pea', 'rpai', 'schiai', 'rpe', 'zoi', 'briai'], dtype=object))

【讨论】:

    【解决方案7】:

    我被证明是错的,我必须使用字典(感谢@Steve)。这是包含字典的更新版本:

    a = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
    b = [None]*len(a)
    d = {}
    for i,x in enumerate(a):
        if x not in d: d[x] = len (d) #or use d.setdefault(x, len(d)) instead of the if statement (using the algo from @superb rain's)
        b[i] = d[x]    
    
    print (a)
    print (b)
    

    这个输出将是:

    ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']
    [0, 1, 1, 2, 0, 3, 4, 4, 5, 3]
    

    【讨论】:

    • 嗯,首先,答案是错误的。其次,使用字典的原因是您不必一遍又一遍地搜索列表,这就是您的代码正在做的事情。所以你的代码效率低下......但它确实避免使用字典。
    • 感谢您查看我的代码。我已经使用字典更新了代码
    • 好多了。不过,您应该进行一项重大修复。当您使用if x not in d.keys()if x not in d 时,您就完全没有使用字典的理由了。您正在从字典中提取整个键列表,这需要时间。然后,您正在对该列表进行线性搜索。所有这一切,而不是直接在字典中查找值,这是字典所擅长的。
    • 感谢您的解释。我现在明白了。没有意识到 d vs d.keys() 的重要性
    • @Steve 对于会员资格测试,x in d 是正确的方法,x in d.keys() 毫无意义且速度较慢(只是没有您想象的那么糟糕 :-)。如果您使用它的类似集合的行为,它为您提供的视图可能会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 2018-08-06
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多