【问题标题】:Map unique strings to integers in Python [duplicate]在Python中将唯一字符串映射到整数[重复]
【发布时间】:2017-04-04 09:25:43
【问题描述】:

我有一个清单,可以说 L = ['apple','bat','apple','car','pet','bat'].

我想把它转换成 Lnew = [ 1,2,1,3,4,2]

每个唯一的字符串都与一个数字相关联。

我有一个使用hashmap 的java 解决方案,但我不知道如何在python 中使用hashmap。 请帮忙。

【问题讨论】:

  • 你尝试了什么?
  • python 中的字典像 hashmap 一样工作
  • @RaminNietzsche,我不能代表 Java 的 hashmap,但是 Python 的 dicts 没有给出提问者想要的整数索引,尤其是按字母顺序排序的(没有特别要求,但在他们想要的输出)。
  • 如何计算出与字符串关联的数字?
  • @RaminNietzsche,不过,您的想法是对的,您可以使用 dict 以这种方式创建映射:d = {k: v for v, k in enumerate(sorted(set(L)))},然后是 Lnew = [d[x] for x in L

标签: python


【解决方案1】:

这里有一个快速的解决方案:

l = ['apple','bat','apple','car','pet','bat']

创建一个将所有唯一字符串映射到整数的字典:

d = dict([(y,x+1) for x,y in enumerate(sorted(set(l)))])

将原始列表中的每个字符串映射到其各自的整数:

print [d[x] for x in l]
# [1, 2, 1, 3, 4, 2]

【讨论】:

  • 我只想添加enumerate(set(sorted(l))),因为提问者没有指定字母排序,但他们想要的输出有它。
  • 另外,你可以使用字典理解:d = {k: v for v, k in enumerate(sorted(set(l)))}
  • 这是否有效取决于OP是否只需要描述的“数字”,或者实际上是输出中显示的第一个索引+1;也使用dict理解
  • [3, 2, 3, 1, 0, 2] 不是 OP 想要的结果,我在这里遗漏了什么吗?
  • 回答者没有对列表进行排序或对映射进行 1 索引。以下将使用相同的方法并给出相同的输出:d = {k: v+1 for v, k in enumerate(sorted(set(L)))},然后是Lnew = [d[x] for x in L]
【解决方案2】:
x = list(set(L))
dic = dict(zip(x, list(range(1,len(x)+1))))

>>> [dic[v] for v in L]
[1, 2, 1, 3, 4, 2]

【讨论】:

  • 当然,如果您希望第一个单词的数字为 1,请使用 x.index(v)+1
  • 仅代码,不是所需的输出,list.index 每次调用 O(n)
  • 不幸的是,有二次运行时间,这可以在 O(n) 中完成。
  • list(set(sorted(L)))[x.index(v)+1... 以获得所需的输出提问者。
【解决方案3】:

您也可以在 Python 中使用 hashmap,但我们称之为 dict

>>> L = ['apple','bat','apple','car','pet','bat']
>>> idx = 1
>>> seen_first = {}
>>>
>>> for word in L:
...     if word not in seen_first:
...         seen_first[word] = idx
...         idx += 1
... 
>>> [seen_first[word] for word in L]
[1, 2, 1, 3, 4, 2]

【讨论】:

  • +1 以获得最明显和最明智的答案;但是{x:len(L)-i for i,x in enumerate(L[::-1])} 来构建字典怎么样
  • @Chris_Rands 我刚刚意识到 OP 不想按索引 + 1,而是给第一个唯一单词编号 1,第二个唯一单词编号 2,依此类推。 (我相应地编辑了我的答案。)
  • 我现在认为他们真正想要的(基于最佳答案)是 stackoverflow.com/questions/42350029/… 但坦率地说,这个问题并不清楚,应该关闭 IMO
  • @Chris_Rands 是的,我现在很困惑。
【解决方案4】:

您可以使用地图字典:

d = {'apple':1, 'bat':2, 'car':3, 'pet':4}
L = ['apple','bat','apple','car','pet','bat']
[d[x] for x in L] # [1, 2, 1, 3, 4, 2]

对于自动创建地图字典,您可以将defaultdict(int) 与计数器一起使用。

from collections import defaultdict
d = defaultdict(int)
co = 1
for x in L:
    if not d[x]:
        d[x] = co
        co+=1
d # defaultdict(<class 'int'>, {'pet': 4, 'bat': 2, 'apple': 1, 'car': 3})

或者正如@Stuart 提到的,您可以使用d = dict(zip(set(L), range(len(L)))) 来创建字典

【讨论】:

  • 我有很多字符串。所以在代码中手动复制是不可行的。
  • @Mustafa 我编辑了你应该如何自动创建字典的答案
  • 您可以使用d = dict(zip(set(L), range(len(L))))自动制作地图
  • @Mustafa 您需要在某处定义字符串和整数之间的映射吗?
【解决方案5】:

你可以试试:

>>> L = ['apple','bat','apple','car','pet','bat']
>>> l_dict = dict(zip(set(L), range(len(L))))
>>> print l_dict
{'pet': 0, 'car': 1, 'bat': 2, 'apple': 3}
>>> [l_dict[x] for x in L]
[3, 2, 3, 1, 0, 2]

【讨论】:

    【解决方案6】:
    Lnew = []
    for s in L:
        Lnew.append(hash(s))  # hash(x) returns a unique int based on string
    

    【讨论】:

    • 从问题来看,我认为他们正在寻找基于 1 的整数,而不是 hash() 给出的非常长的整数。
    • 考虑为您的代码提供解释
    • hash 确实 not 为每个字符串返回一个唯一的 int。哈希冲突are possible.
    • 如果您解释这是有损编码(映射不保证为 1:1 并且可能不完全可逆),则此处的一般方法很好。更大的问题是内置的散列函数对于任何两次运行都不一致。 hashlib 与 blake2s 并减少到 int 会更好。
    猜你喜欢
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多