0

我有一个类似的列表:

["asdf-1-bhd","uuu-2-ggg","asdf-2-bhd","uuu-1-ggg","asdf-3-bhd"]

我想在删除数字后分成两个元素相等的组:

"asdf-1-bhd", "asdf-2-bhd", "asdf-3-bhd"
"uuu-2-ggg" , uuu-1-ggg"

我一直在itertools.groupby使用

for key, group in itertools.groupby(elements, key= lambda x : removeIndexNumber(x)):

但是当要分组的元素不连续时,这不起作用。

我曾考虑过使用列表推导,但这似乎是不可能的,因为组的数量不是固定的。

tl;博士:

我想对东西进行分组,有两个问题:

  1. 我不知道我将获得多少块
  2. 我将被分组到一个块中的元素可能不是连续的
4

2 回答 2

3

你为什么不换个角度想。您可以将所有内容映射到字典中:

import re
from collections import defaultdict
regex = re.compile('([a-z]+\-)\d(\-[a-z]+)')

t = ["asdf-1-bhd","uuu-2-ggg","asdf-2-bhd","uuu-1-ggg","asdf-3-bhd"]

maps = defaultdict(list)

for x in t:
    parts = regex.match(x).groups()
    maps[parts[0]+parts[1]].append(x)

输出:

[['asdf-1-bhd', 'asdf-2-bhd', 'asdf-3-bhd'], ['uuu-2-ggg', 'uuu-1-ggg']]

这真的很快,因为您不必将一件事与另一件事进行比较。

编辑:

以不同的方式思考

您最初的方法是遍历每个项目并将它们相互比较。这是过于复杂和不必要的。

让我们考虑一下我的代码做了什么。首先它得到精简版:

"asdf-1-bhd" -> "asdf--bhd"
"uuu-2-ggg" -> "uuu--ggg"
"asdf-2-bhd" -> "asdf--bhd"
"uuu-1-ggg" -> "uuu--ggg"
"asdf-3-bhd" -> "asdf--bhd"

您已经可以开始查看组了,我们还没有比较任何东西!

我们现在做一种反向映射。我们把右边的所有东西都作为键,把左边的任何东西都放在一个列表中,该列表由左边的值映射:

'asdf--bhd' -> ['asdf-1-bhd', 'asdf-2-bhd', 'asdf-3-bhd']
'uuu--ggg' -> ['uuu-2-ggg', 'uuu-1-ggg']

我们的组由它们的共同计算值(键)定义。这适用于任何数量的元素和组。

于 2013-08-27T02:46:47.167 回答
0

好的,简单的解决方案(在这里肯定为时已晚):

使用itertools.groupby,但首先sort是列表。

至于上面给出的例子:

elements = ["asdf-1-bhd","uuu-2-ggg","asdf-2-bhd","uuu-1-ggg","asdf-3-bhd"]
elemens.sort(key = lambda  x : removeIndex(x))
for key, group in itertools.groupby(elements, key= lambda x : removeIndexNumber(x)):
     for element in group:
         # do stuff

如您所见,排序的条件与分组的条件相同。这样,最终必须分组的元素首先按连续顺序排列。完成后,itertools.groupy就可以正常工作了。

于 2013-08-27T02:44:38.567 回答