【问题标题】:Categorize elements of a list in python在python中对列表的元素进行分类
【发布时间】:2018-07-24 09:04:45
【问题描述】:

我想有效地对给定列表L1 的元素进行分类。此列表可以任意长,因此我正在寻找一种有效的方法来执行以下操作。

列表L1 包含几个元素[e_1,...,e_N],可以与称为areTheSame(e1,e2) 的通用函数进行比较。如果此函数返回True,则表示两个元素属于同一类别。

最后,我想要另一个列表L2,它又包含不同的列表[LC_1, ..., LC_M]。每个LC 列表都包含来自同一类别的所有元素。

【问题讨论】:

  • 我认为你可以用 O(N**2) 时间做到这一点,首先找到唯一的元素,然后在下一个循环中附加相同的类别。
  • 如果areTheSame 传递和反射? IE。将每个元素与每个组的任何一个代表进行比较以确保它是否属于该组就足够了吗?

标签: python python-2.7 list categories


【解决方案1】:

假设函数具有传递性和反射性(如果不是,则整个分组似乎没有多大意义),将每个单词与每个组中的一个“代表”进行比较就足够了,例如只是第一个或最后一个元素。如果不存在这样的组,请创建一个新组,例如使用带有空列表的 next 作为默认元素。

lst = "a list with some words with different lengths".split()
areTheSame = lambda x, y: len(x) == len(y)
res = []
for w in lst:
    l = next((x for x in res if areTheSame(w, x[0])), [])
    if l == []:
        res.append(l)
    l.append(w)

结果:[['a'], ['list', 'with', 'some', 'with'], ['words'], ['different'], ['lengths']]

不过,它的复杂度为 O(n*k),其中 n 是单词数,k 是组数。如果你有一个函数getGroup(x),而不是areTheSame(x,y),那会更有效率,那么你就会有O(n)。也就是说,该函数不会测试两个元素是否属于同一组,而是提取确定元素属于哪个组的属性。在我的示例中,这只是字符串的 len,但在您的情况下,它可能更复杂。

getGroup = lambda x: len(x)
d = collections.defaultdict(list)
for w in lst:
    d[getGroup(w)].append(w)

结果:{1: ['a'], 4: ['list', 'with', 'some', 'with'], 5: ['words'], 9: ['different'], 7: ['lengths']}

【讨论】:

  • 太棒了!我不明白getGroup(x) 会做什么
  • @user3473823 在我的示例中,getGroup(x) 将只返回字符串的len。但是,很难说您的情况是否存在这样的关键功能。将其视为某种散列函数,其中任何组中的每个元素的散列都是相同的。
  • 我认为getGroup(x) 函数在我的情况下不存在。此外,我有处理不可散列元素的问题,因此它们不能用作d 字典中的键。
  • @user3473823 如果它们不能是键,您可以只使用列表列表而不是字典,然后与该列表中的第一个或最后一个元素进行比较,或者如果追加一个新列表没有匹配。关于 key/compare 函数:你的函数看起来如何,或者它到底做了什么?
  • @user3473823 我将第一个版本更改为使用 list-of-lists 而不是 dict,因为 dict 在这里并没有真正的帮助,这样元素就不必是可散列的。跨度>
【解决方案2】:

我相信您可以使用 itertools groupby 函数,但可能需要修改 areTheSame 函数,使其成为 keyfunc,即会产生某种密钥。

L1 = sorted(L1, key=keyfunc)
L2 = [list(g) for _, g in groupby(L1, keyfunc))

【讨论】:

  • 可能很难将areTheSame 转换成键函数。根据函数的不同,cmp_to_key 可能会有所帮助,但我认为这只有在函数返回 0-1/+1 而不是 TrueFalse 时才有效。
猜你喜欢
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
相关资源
最近更新 更多