假设我有一个像这样的列表
myList = ['A_x','B_x','C_x','D_x']
以及像这样的列表
myListOfList = [['A_x','B_y','C_x','D_z'],
['A_y','B_y','C_y','D_y'],
['A_u','B_y','C_y','D_y'],
['A_y','C_y','B_y','D_y', 'E_l'],
['A_y','P_y','T_y','D_y'],
['A_y','B_y','C_y'],
['A_y','C_y','D_y','B_y'],
['A_z','C_z','D_z','B_z']]
现在我想确定myListOfList
中与myList
相同的所有列表,除了这些列表中各个元素的后缀,其中{{1}子列表中元素的后缀必须是相同的。所以在上面的例子中,我想找到:
myListOfList
但我不想找到其他的元素,因为它们的元素没有相同的后缀,长度与#all elements as in myList but with suffix y instead of x
['A_y','B_y','C_y','D_y']
#all elements as in myList but with suffix y instead of x but in different order
['A_y','C_y','D_y','B_y']
#all elements as in myList but with suffix z instead of x but in different order
['A_z','C_z','D_z','B_z']
长度不同,或者元素的第一部分与{{1}中的元素不同}}
我实现了如下:
myList's
这确实给出了正确的输出:myList
。
解释此代码的两个元素:
这将检查列表myList = ['A_x','B_x','C_x','D_x']
myListOfList = [['A_x','B_y','C_x','D_z'],
['A_y','B_y','C_y','D_y'],
['A_u','B_y','C_y','D_y'],
['A_y','C_y','B_y','D_y', 'E_l'],
['A_y','P_y','T_y','D_y'],
['A_y','B_y','C_y'],
['A_y','C_y','D_y','B_y'],
['A_z','C_z','D_z','B_z']]
listOfInd=[]
for ind, sl in enumerate(myListOfList):
if len(sl) == len(myList) and [x.endswith(sl[0][-2:]) for x in sl].count(False) == 0:
tempList = zip(myList, sorted(sl))
allTrue = True
for el in tempList:
#print el[0]
if el[0][:-2] != el[1][:-2]:
allTrue = False
if(allTrue):
listOfInd.append(ind)
中的所有元素是否具有相同的后缀:
listOfInd = [1, 6, 7]
检查字符串sl
是否相同,但后缀(字符串的最后两个元素)除外:
[x.endswith(sl[0][-2:]) for x in sl].count(False) == 0
所以我要做的是遍历el
中的每个列表,如果此列表中的元素数与if el[0][:-2] != el[1][:-2]
中的元素数相同,并且此列表中的所有元素具有相同的后缀,I myListOfList
此列表包含myList
。然后我浏览这个压缩列表中的每个元素,并比较字符串直到后缀。
代码工作,然而,它看起来非常低效,我想知道是否有更多" pythonic"在没有这么多循环的情况下这样做。谁能想到更有效的实现方法呢?
答案 0 :(得分:1)
这是我用套装刺我的。请注意,我正在使用字符串子索引而不是拆分'_'或正则表达式,因为我假设格式非常严格。
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_Q) {
shortPress = false;
Toast.makeText(this, "longPress", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_Q) {
if(event.getAction() == KeyEvent.ACTION_DOWN){
event.startTracking();
if(event.getRepeatCount() == 0){
shortPress = true;
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_G) {
if(shortPress){
Toast.makeText(this, "shortPress", Toast.LENGTH_SHORT).show();
}
shortPress = false;
return true;
}
return super.onKeyUp(keyCode, event);
}
答案 1 :(得分:1)
如果是前缀,请设置一个集合,检查前缀集是否是子列表中每个元素的前缀的子集,如果是,则检查所有后缀是否相同。
st = {s[0] for s in myList}
l = []
for ind, sub in enumerate(myListOfList):
k = sub[0][-1]
if st.issubset(ch[0] for ch in sub) and all((ch[-1] == k for ch in sub)):
l.append(ind)
print(l)
[1, 6, 7]
如果您愿意,可以将它放在列表中:
inds = [ind for ind, sub in enumerate(myListOfList) if st.issubset(ch[0] for ch in sub)
and all(ch[-1] == sub[0][-1] for ch in sub)]
print(inds)
[1, 6, 7]
你也可以进行一些优化,如果任何sub的长度不等于myList的长度我们就不能有匹配:,我们可以使用all来查看每个sub的每个元素[0]是否是在集合中可能会更快一点。
l = []
ln_m = len(myList)
for ind, sub in enumerate(myListOfList):
k = sub[0][-1]
if len(sub) == ln_m and all(ch[0] in st for ch in sub) and all(ch[-1] == k for ch in sub):
l.append(ind)
答案 2 :(得分:1)
def compare(l1,l2):
def normalize(l):
r = defaultdict(set)
for a,b in map(lambda x: x.split('_'), l): r[b].add(a)
return set(tuple(sorted(v)) for v in r.values())
n1,n2 = normalize(l1),normalize(l2)
return len(n1)==1 and len(n2)==1 and n1==n2
测试:
>>> [i for i,l in enumerate(myListOfList) if compare(myList,l)]
[1, 6, 7]
关于compare()函数中的normalize()函数的一点注意事项:它将为每个后缀创建一组排序前缀:
>>> normalize(myList)
{('A', 'B', 'C', 'D')}
>>> normalize(['A_x','B_x','C_x','D_y'])
{('A', 'B', 'C'), ('D',)}
>>> normalize(['A_x','B_y','C_z','D_x'])
{('A', 'D'), ('B',), ('C',)}
实际上,如果删除len(n1)==1 and len(n2)==1
条件,您可以将评论中的列表与问题进行比较。