在 Python 中对两个列表进行相减和相加而不改变它们的顺序

发布于 2024-11-27 02:22:00 字数 297 浏览 4 评论 0原文

如果我有列表 [68,31,93,35,10] (所有数字都会不同)和列表 [93,0,22,10,99,33, 21,9] (同样,所有数字都会不同,但可能与其他列表重叠),我需要能够准确地得到[68,31,93,35,10,0,22,99,33,21,9],其中第二个列表附加到第一个列表且不重复。我还需要能够准确获取 [68,31,35],其中第一个列表已删除第二个列表中的所有重复项。输出的顺序应始终与输入的顺序相同。我该怎么办? (如果简单的话,一个衬垫就很好了。)

If I have the list [68,31,93,35,10] (all the numbers will be different) and the list [93,0,22,10,99,33,21,9] (again, all the numbers will be different, but may overlap the other list), I need to be able to get exactly [68,31,93,35,10,0,22,99,33,21,9], where the second list is appended to the first list without duplicates. I also need to be able to get exactly [68,31,35] where the first list has all duplicates in the second list removed. The output always should be the same order as the input. How do I go about this? (A one liner would be nice if it were simple.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蓝天 2024-12-04 02:22:00
l1 = [68, 31, 93, 35,10]
l2 = [93, 0, 22, 10, 99, 33, 21,9]

l1 + [x for x in l2 if not x in l1]
# [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]

[x for x in l1 if not x in l2]
# [68, 31, 35]

编辑:对于长列表,您不想进行所有这些列表查找。这是另外两个食谱:

联合:

from collections import OrderedDict
OrderedDict().fromkeys(l1+l2).keys()
# [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]

差异:

s = set(l2)
[x for x in l1 if not x in s]
# [68, 31, 35]
l1 = [68, 31, 93, 35,10]
l2 = [93, 0, 22, 10, 99, 33, 21,9]

l1 + [x for x in l2 if not x in l1]
# [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]

[x for x in l1 if not x in l2]
# [68, 31, 35]

EDIT: for long lists, you don't want to do all those list lookups. Here are two other recipes:

union:

from collections import OrderedDict
OrderedDict().fromkeys(l1+l2).keys()
# [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]

difference:

s = set(l2)
[x for x in l1 if not x in s]
# [68, 31, 35]
喜爱纠缠 2024-12-04 02:22:00

假设输入 l1l2,您可以使用以下方法计算它们的有序并集:

l1 + filter(lambda x: x not in l1, l2)

要获得有序差值 l1 - l2,请写入

filter(lambda x: x not in l2, l1)

或者,使用列表推导式:

>>> l1 = [68,31,93,35,10]
>>> l2 = [93,0,22,10,99,33,21,9]
>>> l1 + [el2 for el2 in l2 if el2 not in l1]
[68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> [el1 for el1 in l1 if el1 not in l2]
[68, 31, 35]

如果您这样做对于非常大的列表(其中性能是一个问题),构造一个 set 以加快查找速度:

>>> sl1 = set(s1)
>>> l1 + [el2 for el2 in l2 if el2 not in sl1]
[68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> sl2 = set(s2)
>>> [el1 for el1 in l1 if el1 not in sl2]
[68, 31, 35]

Assuming inputs l1 and l2, you can calculate their ordered union with:

l1 + filter(lambda x: x not in l1, l2)

To get the ordered difference l1 - l2, write

filter(lambda x: x not in l2, l1)

Alternatively, use list comprehensions:

>>> l1 = [68,31,93,35,10]
>>> l2 = [93,0,22,10,99,33,21,9]
>>> l1 + [el2 for el2 in l2 if el2 not in l1]
[68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> [el1 for el1 in l1 if el1 not in l2]
[68, 31, 35]

If you're doing this with very large list (where performance is an issue), construct a set for faster lookup:

>>> sl1 = set(s1)
>>> l1 + [el2 for el2 in l2 if el2 not in sl1]
[68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> sl2 = set(s2)
>>> [el1 for el1 in l1 if el1 not in sl2]
[68, 31, 35]
不必了 2024-12-04 02:22:00
def unique_chain(*iters):
    seen = set()
    for it in iters:
        for item in it:
            if item not in seen:
                yield item
                seen.add(item)

print list(unique_chain([68, 31, 93, 35,10], [93, 0, 22, 10, 99, 33, 21,9]))
def unique_chain(*iters):
    seen = set()
    for it in iters:
        for item in it:
            if item not in seen:
                yield item
                seen.add(item)

print list(unique_chain([68, 31, 93, 35,10], [93, 0, 22, 10, 99, 33, 21,9]))
梦回梦里 2024-12-04 02:22:00
>>> a = [68,31,93,35,10]
>>> b = [93,0,22,10,99,33,21,9]
>>> result= []
>>> temp = a + b
>>> [result.append(x) for x in temp if x not in result]
>>> result
    [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> a = set(a)
>>> b = set(b)
>>> a - b
    set([35, 68, 31])
>>> a = [68,31,93,35,10]
>>> b = [93,0,22,10,99,33,21,9]
>>> result= []
>>> temp = a + b
>>> [result.append(x) for x in temp if x not in result]
>>> result
    [68, 31, 93, 35, 10, 0, 22, 99, 33, 21, 9]
>>> a = set(a)
>>> b = set(b)
>>> a - b
    set([35, 68, 31])
滿滿的愛 2024-12-04 02:22:00

也许你可以使用 OrderedSet

import collections

class OrderedSet(collections.MutableSet):
    def __init__(self, iterable, *args, **kwargs):
        super(OrderedSet, self).__init__(*args, **kwargs)
        self._data = collections.OrderedDict()
        self.update(iterable)

    def update(self, iterable):
        self._data.update((x, None) for x in iterable)

    def __iter__(self):
        return iter(self._data)

    def __contains__(self, value):
        return value in self._data

    def __len__(self):
        return len(self._data)

    def __le__(self, other):
        if isinstance(other, OrderedSet):
            return self._data <= other._data
        return super(OrderedSet, self).__le__(other)

    def __and__(self, other):
        # Overrided by make the order of self the preferred one
        if isinstance(other, collections.Set):
            return self._from_iterable(value for value in self 
                                             if value in other)
        return self & set(other)

    def __ior__(self, other):
        self.update(other)
        return self

    def add(self, value):
        self._data[value] = None

    def discard(self, value):
        self._data.pop(value, None)

    def __repr__(self):
        return "%s(%r)" % (type(self).__name__, self._data.keys())

Maybe you could use an OrderedSet

import collections

class OrderedSet(collections.MutableSet):
    def __init__(self, iterable, *args, **kwargs):
        super(OrderedSet, self).__init__(*args, **kwargs)
        self._data = collections.OrderedDict()
        self.update(iterable)

    def update(self, iterable):
        self._data.update((x, None) for x in iterable)

    def __iter__(self):
        return iter(self._data)

    def __contains__(self, value):
        return value in self._data

    def __len__(self):
        return len(self._data)

    def __le__(self, other):
        if isinstance(other, OrderedSet):
            return self._data <= other._data
        return super(OrderedSet, self).__le__(other)

    def __and__(self, other):
        # Overrided by make the order of self the preferred one
        if isinstance(other, collections.Set):
            return self._from_iterable(value for value in self 
                                             if value in other)
        return self & set(other)

    def __ior__(self, other):
        self.update(other)
        return self

    def add(self, value):
        self._data[value] = None

    def discard(self, value):
        self._data.pop(value, None)

    def __repr__(self):
        return "%s(%r)" % (type(self).__name__, self._data.keys())
情痴 2024-12-04 02:22:00

如此定义前两个列表后,

a = [68,31,93,35,10]
b = [93,0,22,10,99,33,21,9]

这是第一个问题的单行解决方案,

c = [x for x in a+b if x not in set(a).intersection(set(b))]

以及第二个问题的单行解决方案,

d = [x for x in a+b if x not in b]

After defining the first two lists as such,

a = [68,31,93,35,10]
b = [93,0,22,10,99,33,21,9]

Here is the one-line solution to the first problem,

c = [x for x in a+b if x not in set(a).intersection(set(b))]

And the one-liner to the second problem,

d = [x for x in a+b if x not in b]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文