比较关于各自元素后缀的字符串列表

时间:2015-06-28 19:43:21

标签: python performance list string-comparison

假设我有一个像这样的列表

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"在没有这么多循环的情况下这样做。谁能想到更有效的实现方法呢?

3 个答案:

答案 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条件,您可以将评论中的列表与问题进行比较。