假设我们有一个列表清单如下:
S1 = [{'A_1'}, {'B_1', 'B_3'}, {'C_1'}, {'A_3'}, {'C_2'},{'B_2'}, {'A_2'}]
S2 = []
我想查看此列表,并检查每组检查该集合与该列表的其他集合之间的属性是否为真。然后,如果该属性成立,则将这两个集合连接在一起,并将新集合与其他S1集合进行比较。最后,将这个新集添加到S2。
现在,作为示例,假设我们说如果这两个集合中的所有元素都以相同的字母开头,则属性保持在两个集合之间。 对于上面描述的列表S1,我希望S2为:
S2 = [{'A_1', 'A_3', 'A_2'}, {'B_1', 'B_3', 'B_2'}, {'C_1','C_2'}]
我们应该如何为此编写代码?
这是我的代码。它工作正常,但我认为它效率不高,因为它试图多次添加集([' A_3',' A_2',#A;'])。 假设给出了Checker函数,它检查两个列表之间的属性。我上面提到的那个属性只是一个例子。我们可能想稍后改变它。所以,我们应该将Checker作为一个函数。
def Checker(list1, list2):
flag = 1
for item1 in list1:
for item2 in list2:
if item1[0] != item2[0]:
flag =0
if flag ==1:
return 1
else:
return 0
S1 = [{'A_1'}, {'B_1', 'B_3'}, {'C_1'}, {'A_3'}, {'C_2'},{'B_2'}, {'A_2'}]
S2 = []
for i in range(0,len(S1)):
Temp = S1[i]
for j in range(0,i-1) + range(i+1,len(S1)):
if Checker(Temp,S1[j]) == 1:
Temp = Temp.union(S1[j])
if Temp not in S2:
S2.append(Temp)
print S2
输出:
[set(['A_3', 'A_2', 'A_1']), set(['B_1', 'B_2', 'B_3']), set(['C_1', 'C_2'])]
答案 0 :(得分:1)
您可以使用it.chain(*nested_list)
作为sorted
,然后使用{{1}来展平(很多方法可以使用key
}和it.groupby()
列表。使用相同的key
创建新列表:
In []:
import operator as op
import itertools as it
prop = op.itemgetter(0)
[set(v) for _, v in it.groupby(sorted(it.chain(*S1), key=prop), key=prop)]
Out[]:
[{'A_1', 'A_2', 'A_3'}, {'B_1', 'B_2', 'B_3'}, {'C_1', 'C_2'}]
答案 1 :(得分:1)
def Checker(list1, list2):
flag = 1
for item1 in list1:
for item2 in list2:
if item1[0] != item2[0]:
return 0
return 1
我试图降低Checker()
功能的复杂性。
答案 2 :(得分:0)
S1 = [{'A_1'}, {'B_1', 'B_3'}, {'C_1'}, {'A_3'}, {'C_2'},{'B_2'}, {'A_2'}]
from itertools import chain
l = list( chain.from_iterable(S1) )
s = {i[0] for i in l}
t = []
for k in s:
t.append([i for i in l if i[0]==k])
print (t)
输出:
[['B_1', 'B_3', 'B_2'], ['A_1', 'A_3', 'A_2'], ['C_1', 'C_2']]
答案 3 :(得分:0)
如果考虑性能,我建议使用python中的canoncical分组方法:使用defaultdict
:
>>> S1 = [{'A_1'}, {'B_1', 'B_3'}, {'C_1'}, {'A_3'}, {'C_2'},{'B_2'}, {'A_2'}]
>>> from collections import defaultdict
>>> grouper = defaultdict(set)
>>> from itertools import chain
>>> for item in chain.from_iterable(S1):
... grouper[item[0]].add(item)
...
>>> grouper
defaultdict(<class 'set'>, {'C': {'C_1', 'C_2'}, 'B': {'B_1', 'B_2', 'B_3'}, 'A': {'A_1', 'A_2', 'A_3'}})
注意,以下内容适用于Python 3.在Python 2中,.values
返回一个列表。
注意,你可能实际上只是想要这个dict
,它可能比你的组列表更有用。您还可以使用.values()
方法,该方法返回值的视图:
>>> grouper.values()
dict_values([{'C_1', 'C_2'}, {'B_1', 'B_2', 'B_3'}, {'A_1', 'A_2', 'A_3'}])
如果你真的想要一个列表,你总是可以直接得到它:
>>> S2 = list(grouper.values())
>>> S2
[{'C_1', 'C_2'}, {'B_1', 'B_2', 'B_3'}, {'A_1', 'A_2', 'A_3'}]
假设N是所有嵌套集中的项数,则此解为O(N)。
答案 4 :(得分:0)
你的财产是1.对称的和2.传递的?即{。prop(a,b)
当且仅当prop(b,a)
和2. prop(a,b)
和prop(b,c)
隐含prop(a,c)
时?如果是这样,您可以编写一个带有集合的函数,并为相应的等价类提供一些代码。 E.g。
1 S1 = [{'A_1'}, {'B_1', 'B_3'}, {'C_1'}, {'A_3'}, {'C_2'},{'B_2'}, {'A_2'}]
2
3 def eq_class(s):
4 fs = set(w[0] for w in s)
5 if len(fs) != 1:
6 return None
7 return fs.pop()
8
9 S2 = dict()
10 for s in S1:
11 cls = eq_class(s)
12 S2[cls] = S2.get(cls,set()).union(s)
13
14 S2 = list(S2.values())
这具有分摊O(len(S1))
的优势。另请注意,如果1或2失败,您的最终输出可能取决于S1
的顺序。
答案 5 :(得分:0)
使用itertools.groupby
from itertools import groupby
S1 = [['A_1'], ['B_1', 'B_3'], ['C_1'], ['A_3'], ['C_2'],['B_2'], ['A_2']]
def group(data):
# Flatten the data
l = list((d for sub in data for d in sub))
# Sort it
l.sort()
groups = []
keys = []
# Iterates for each group found only
for k, g in groupby(l, lambda x: x[0]):
groups.append(list(g))
keys.append(k)
# Return keys group data
return keys, [set(x) for x in groups]
keys, S2 = group(S1)
print "Found the following keys", keys
print "S2 = ", S2
这里的主要想法是减少og append
的数量,因为这真的削弱了性能。我们使用生成器对数据进行展平并对其进行排序。然后我们使用groupby
对数据进行分组。循环仅每组迭代一次。此处仍有相当多的数据副本可能被删除。
奖励是该功能还会返回数据中检测到的组密钥。