4

免責事項: 私は経験豊富な Python ユーザーではありません。

あるタスクに遭遇したので、Python でそれを行う最もエレガントな方法を見つけようとしています。

タスク自体は次のとおりです。指定された文字列の a がs のリスト (それぞれ0 から N - 1 まで、N はリスト内の一意の文字列の数) をlist返します。ここで、各 int は最初のリストの特定の文字列に対応します。同じ文字列は同じ番号、異なる文字列、つまり異なる番号にマップする必要があります。intint

私が最初に思いついたのは、「少し」複雑すぎるようです。

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]
4

5 に答える 5

4

辞書内包表記とリスト内包表記を使用できます。

>>> 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)}
于 2013-09-16T10:41:08.573 に答える
2

アプローチ文字の順序を保持したい場合、 set を使用したアプローチはエラーにつながる可能性があると思います。実際には、あなたの例でそれを見ることができます - 'b'get index2の代わりに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]
于 2013-09-16T10:43:35.980 に答える
1

速度ではなく、読みやすさを重視:indexリスト内包表記で list メソッドを使用します。

>>> 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]
于 2013-09-16T10:43:35.183 に答える
0

最初にリストから一意の文字列を取得して列挙します。これにより、各文字列に (0 から N-1 までの) 番号が割り当てられます。次に、文字列ごとにこの値を取得し、リストに入れます。1行でそれがどのように行われるかを次に示します。

a = ["a","b","a","c","b","a"]
[{s:i for i, s in enumerate(set(a))}[s] for s in a]
于 2013-09-16T10:45:21.000 に答える
0

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]
于 2013-09-16T11:31:45.813 に答える