【问题标题】:Enumerate unique strings in list枚举列表中的唯一字符串
【发布时间】:2013-09-16 10:29:40
【问题描述】:

免责声明:我不是经验丰富的 Python 用户。

我遇到了一个任务,现在我正试图找出用 Python 完成它的最优雅的方法。

这是任务本身:给定一个 list 字符串返回一个 ints 列表(每个 int 从 0 到 N - 1,其中 N 是列表中唯一字符串的数量),其中每个int 对应于初始列表中的某个字符串。相同的字符串应该映射到相同的数字,不同的字符串 - 映射到不同的数字。

我想出的第一件事似乎“有点”过于复杂:

a = ["a","b","a","c","b","a"]
map(lambda x: dict(map(lambda x: reversed(x), enumerate(set(a))))[x], a)

上面代码的结果:

[0, 2, 0, 1, 2, 0]

【问题讨论】:

    标签: python list python-2.7


    【解决方案1】:

    您可以使用 dict 和列表推导:

    >>> a = ["a","b","a","c","b","a"]
    >>> d = {x:i for i, x in enumerate(set(a))}
    >>> [d[item] for item in a]
    [0, 2, 0, 1, 2, 0]
    

    为了保持秩序:

    >>> seen = set()
    >>> d = { x:i for i, x in enumerate(y for y in a
                                           if y not in seen and not seen.add(y))}
    >>> [d[item] for item in a]
    [0, 1, 0, 2, 1, 0]
    

    上面的dict理解等价于:

    >>> seen = set()
    >>> lis = []
    for item in a:
        if item not in seen:
            seen.add(item)
            lis.append(item)
    ...         
    >>> lis
    ['a', 'b', 'c']
    >>> d = {x:i for i,x in enumerate(lis)}
    

    【讨论】:

    • +1 表示第二个,但你不觉得它可能有点难吗?
    • 我认为{x:i for i, x in reverse(list(enumerate(a)))} 会让你保持秩序
    • @Eric 但是对于c,它将返回3
    • @AshwiniChaudhary:哎呀
    【解决方案2】:

    如果您想保留接近字符的顺序,我认为您使用 set 的方法可能会导致错误。实际上,您可以在示例中看到它 - 'b' 得到索引 2 而不是 1。如果你想保持秩序,你可以使用OrderedDict

    >>> a = ["a","b","a","c","b","a"]
    >>> d = {x:i for i, x in enumerate(OrderedDict(izip(a, a)).values())}
    >>> [d[x] for x in a]
    [0, 1, 0, 2, 1, 0]
    

    【讨论】:

    • 我并不担心字符串顺序,但这是一个有趣的功能,感谢您的提示。
    【解决方案3】:

    强调可读性,而不是速度:我会使用带有列表理解的列表index 方法:

    >>> a = ["a","b","a","c","b","a"]
    >>> b = list(set(a))
    >>> c = [b.index(x) for x in a]
    >>> c
    [0, 2, 0, 1, 2, 0]
    

    【讨论】:

    • 在我看来,index 会导致解释器为a 中的每个项目遍历b,这大约是 O(n^2)。不过,我可能是错的。基于dict 的解决方案应该(至少,我希望如此)平均为 O(n)。
    • 确实如此。我选择了最易读的解决方案,没有过多考虑性能。
    【解决方案4】:

    首先从列表中获取唯一的字符串并枚举它,因此每个字符串都有一个数字(从 0 到 N-1)。然后为每个字符串获取此值,并将其放入列表中。这是它是如何完成的,在一行中:

    a = ["a","b","a","c","b","a"]
    [{s:i for i, s in enumerate(set(a))}[s] for s in a]
    

    【讨论】:

      【解决方案5】:

      您也可以使用 defaultdict 和 count 迭代器。

      >>> from collections import defaultdict
      >>> from itertools import count
      >>> a = ["a","b","a","c","b","a"]
      >>> x = defaultdict(count().next)
      >>> [x[i] for i in a]
      [0, 1, 0, 2, 1, 0]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-19
        • 2010-10-18
        相关资源
        最近更新 更多