简体   繁体   English

比较两个列表的元素

[英]compare elements of two lists

A = [a1, a2, a3...]  #a1<a2<a3...
B = [b1, b2...]  #b1<b2<b3...

A and B are disjoint. A和B是不相交的。 are I do not know the number of elements and the value of them in A/B in advance. 我是不是事先知道A / B中元素的数量和它们的价值。 I want to compare the value of the elements in both list and delete elements iff: 我想比较list和delete元素iff中元素的值:

delete a[i+1] if there is no b[j] such that a[i]<b[j]<a[i+1]
delete b[i+1] if there is no a[j] such that b[i]<a[j]<b[i+1]

At the end, I want to separate list, not a combination of A and B. 最后,我想分开列表,而不是A和B的组合。

For example, If A[0] < B[0] , A = [1, 10, 40], B = [15, 30]. 例如,如果A[0] < B[0] ,A = [1,10,40],B = [15,30]。 Compare A[1] and B[0] first. 首先比较A[1]B[0] Delete 10 because no element in B are in between 1 and 15. Then delete 15 since no element exist anymore btw 15 and 30. The output should be: if you try to order the elements of the new 2 lists, it should be A[0]<B[0]<A[1]<B[1]<... 删除10因为B中没有元素在1和15之间。然后删除15因为不再存在任何元素btw 15和30.输出应该是:如果你尝试排序新2列表的元素,它应该是A[0]<B[0]<A[1]<B[1]<...

If A[0] > B[0] , vice versa. 如果A[0] > B[0] ,反之亦然。

I came up with this before you edit. 在编辑之前我想出了这个。 But it seems the output is not what you expect. 但似乎输出不是你所期望的。 Anyway, it might help you get on the right track: 无论如何,它可能会帮助您走上正确的轨道:

a = range(0, 30, 3)
b = range(0, 20, 2)

a.sort()
b.sort()

A = [a[i+1] for i in range(len(a)-1) if any(a[i]<b[j]<a[i+1] for j in range(len(b)-1))]
B = [b[i+1] for i in range(len(b)-1) if any(b[i]<a[j]<b[i+1] for j in range(len(a)-1))]

result = sorted(A+B)

print a, b
print result

This is "literally" what you expressed, but the result here is not what you expect. 这是“字面上”你所表达的,但result并不是你所期望的。 I'll try to improve this. 我会尽力改善这一点。

a = [1, 10, 40]
b = [15, 30]

srcs = [a, b]
dsts = [[], []]
prev_which = -1
while all(srcs):
    which = int(srcs[0][0] > srcs[1][0])
    elem = srcs[which].pop(0)
    if prev_which != which:
        dsts[which].append(elem)
    prev_which = which
for src, dst in zip(srcs,dsts):
    if src:
        dst.append(src.pop(0))
a, b = dsts

returns: 收益:

a = [1, 40]
b = [15]

and for 并为

a = [3, 4, 6, 7, 8, 9]
b = [1, 2, 5, 10]

it returns [3, 6] and [1, 5, 10] . 它返回[3, 6][1, 5, 10]

EDIT : another possibility: 编辑 :另一种可能性:

import itertools as it
import operator as op

a = [3, 4, 6, 7, 8, 9]
b = [1, 2, 5, 10]
srcs = [a, b]
dsts = [[], []]

for which, elems in it.groupby(sorted((x, i) for i in (0,1) for x in srcs[i]), key=op.itemgetter(1)):
    dsts[which].append(next(elems)[0])
a, b = dsts

I knew using the bisect module could be a good solution: 我知道使用bisect模块可能是一个很好的解决方案:

>>> def sort_relative(L1, L2):
    # Switch if needed
    if L1[0] > L2[0]:
        L1, L2 = L2, L1
    i = 0
    while i + 1 < max(len(L1), len(L2)):
        try:
            # We know that L1[i] < L2[i]
            # Get indexes where L2[i] and L2[i + 1] should be inserted
            i11 = bisect.bisect_left(L1, L2[i])
            i12 = bisect.bisect_left(L1, L2[i + 1])

            # This condition allows to know if one element of L1
            # was found between L2[i] and L2[i + 1]:
            # - if so, we have L1[i] < L2[i] < L1[i + 1] < L2[i + 1]
            # - else we have L1[i] < L2[i] < L1[i + 1] but
            # we don't know between L1[i + 1] and L2[i + 1]
            if L1[i11] < L2[i + 1]:
                L1 = L1[:i + 1] + [L1[i11]] + L1[i12:]
                index1, index2 = i + 1, i + 2
            else:
                L1 = L1[:i + 1] + L1[i12:]
                index1, index2 = i, i + 1

            # Do the same kind of symetric search,
            # with indexes computed above
            i21 = bisect.bisect_left(L2, L1[index1])
            i22 = bisect.bisect_left(L2, L1[index2])
            if L2[i21] < L1[index2]:
                L2 = L2[:index1] + [L2[i21]] + L2[i22:]
            else:
                L2 = L2[:index1] + L2[i22:]
        # Little trick not to test indexes everywhere:
        # lists are browsed at the same time
        except IndexError:
            pass

        # Next index !
        i += 1

    # Show result
    print 'L1:', L1, '- L2:', L2


>>> sort_relative([1, 10, 50], [15, 30])
L1: [1, 50] - L2: [15]
>>> sort_relative([17, 18, 50], [15, 30])
L1: [15, 30] - L2: [17, 50]
>>> sort_relative([1, 10, 12, 25, 27, 50], [15, 30, 70])
L1: [1, 25, 50] - L2: [15, 30, 70]
>>> sort_relative([1, 10, 12, 25, 27, 50], [15, 30, 34, 70])
L1: [1, 25, 50] - L2: [15, 30, 70]
>>> 

I didn't take into account the case when a number is both in A and B . AB都有数字时,我没有考虑到这种情况。

So, if I am reading correctly, the desired output from your example is [1,40] and [15], yes? 所以,如果我正确阅读,你的例子中所需的输出是[1,40]和[15],是吗?

If so, the following would get the right result, but I am certain there is a tighter way to do it. 如果是这样,以下将得到正确的结果,但我确信有更严格的方法来做到这一点。

a = [1, 10, 40]
b = [15, 30]
c = sorted([[e_a,'a'] for e_a in a] + [[e_b,'b'] for e_b in b])
indices = []

for i in range(len(c)-1):
    if c[i][1] == c[i+1][1]:
        indices.append(i+1)

for e in sorted(indices, reverse=True):
    del c[e]

a,b = [e[0] for e in c if e[1]=='a'],[e[0] for e in c if e[1]=='b']

First - Merging the lists and sorting them, while keeping track of which list they came from. 首先 - 合并列表并对它们进行排序,同时跟踪它们来自哪个列表。

Second - Then remove all instances where the next item in the merged list is from the same source list. 秒 - 然后删除合并列表中下一个项目来自同一源列表的所有实例。

Third - updating a and b. 第三 - 更新a和b。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM