将对象列表转换为整数列表和查找表

4 投票
7 回答
1534 浏览
提问于 2025-04-15 14:12

为了说明我的意思,这里有一个例子

messages = [
  ('Ricky',  'Steve',  'SMS'),
  ('Steve',  'Karl',   'SMS'),
  ('Karl',   'Nora',   'Email')
]

我想把这个列表和一组定义转换成一个整数列表和一个查找字典,这样组里的每个元素都能得到一个独特的ID。这个ID应该像这样映射到查找表中的元素

messages_int, lookup_table = create_lookup_list(
              messages, ('person', 'person', 'medium'))

print messages_int
[ (0, 1, 0),
  (1, 2, 0),
  (2, 3, 1) ]

print lookup_table
{ 'person': ['Ricky', 'Steve', 'Karl', 'Nora'],
  'medium': ['SMS', 'Email']
}

我在想有没有一种优雅且符合Python风格的解决方案来处理这个问题。

我也希望能有比create_lookup_list更好的术语来描述这个。

7 个回答

2

在Otto的回答中(或者其他任何使用字符串到ID字典的回答),如果你特别在意速度的话,我会把:

# create the lookup table
lookup_dict = {}
for group in indices:
    lookup_dict[group] = sorted(indices[group].keys(),
            lambda e1, e2: indices[group][e1]-indices[group][e2])

换成

# k2i must map keys to consecutive ints [0,len(k2i)-1)
def inverse_indices(k2i):
    inv=[0]*len(k2i)
    for k,i in k2i.iteritems():
        inv[i]=k
    return inv

lookup_table = dict((g,inverse_indices(gi)) for g,gi in indices.iteritems()) 

这样做更好,因为直接给反向数组中的每个项目赋值,比排序要快。

2

我的代码长度和复杂度差不多:

import collections

def create_lookup_list(messages, labels):

    # Collect all the values
    lookup = collections.defaultdict(set)
    for msg in messages:
        for l, v in zip(labels, msg):
            lookup[l].add(v)

    # Make the value sets lists
    for k, v in lookup.items():
        lookup[k] = list(v)

    # Make the lookup_list
    lookup_list = []
    for msg in messages:
        lookup_list.append([lookup[l].index(v) for l, v in zip(labels, msg)])

    return lookup_list, lookup
3

defaultdictitertools.count().next 方法结合起来,是给独特的项目分配标识符的好方法。下面是一个如何在你的情况下应用这个方法的例子:

from itertools import count
from collections import defaultdict

def create_lookup_list(data, domains):
    domain_keys = defaultdict(lambda:defaultdict(count().next))
    out = []
    for row in data:
        out.append(tuple(domain_keys[dom][val] for val, dom in zip(row, domains)))
    lookup_table = dict((k, sorted(d, key=d.get)) for k, d in domain_keys.items())
    return out, lookup_table

补充说明:请注意,在 Python 3 中,count().next 变成了 count().__next__ 或者 lambda: next(count())

撰写回答