【问题标题】:Identify new elements in a list [python]识别列表中的新元素 [python]
【发布时间】:2019-11-07 08:40:20
【问题描述】:

我有一个不断更新的列表,其中包含重复的元素,例如


# 10 elements
some_list = ['hello', 'hi', 'bye', 'hello', 'okay']

所以我将列表索引和列表元素一起使用并散列它们,以创建唯一的散列并将它们存储在 redis 上。

因为,这在 True 中运行,我需要不断检查列表末尾的新元素,当列表不断更新和增长时,它会起作用, 但是在特定条件下,列表会重置,以便在末尾添加一个新元素并删除起始元素(这是一个有效的情况)。

新列表如下所示:

# 10 elements
some_list = ['hi', 'bye', 'hello', 'okay', 'new_element']

在这种情况下,由于每个元素的索引都发生了变化,因此哈希值不同,它将每个元素都放入redis中。

任何可以帮助我确定如何在添加新元素的同时识别旧元素的解决方案,我们将不胜感激。

如果提供的信息不明确或不充分,请发布 cmets。

【问题讨论】:

  • 你能添加你到目前为止尝试的内容吗
  • 我不确定我是否可以共享代码,因为它与工作相关,但 hash('hi' + index of 'hi') 用于计算哈希值,并且存储在redis
  • 你能否制作第二个列表,否则与第一个列表相同,但在这种情况下它不会“重置”,并将其与第一个列表进行比较以查找重复元素?

标签: python python-3.x list hash


【解决方案1】:

如果可能的话,您可以通过使用有序字典来解决问题。然后,您可以使用这些键作为簿记参数来检查新元素。

【讨论】:

  • 我现在可以改变我的架构,但我不明白我将如何准确地使用有序字典来管理新元素,元素也可以重复自己(如果使用元素作为关键是您答案的一部分)
  • @piyushdaga 这取决于您添加元素和检查元素的准确程度,但我可能会使用整数作为键索引每个新元素以及您想要存储的值作为值。这样,每一个“曾经”都被分配给一个修复索引。它们索引您可以存储在列表中,并从中(可能通过列表长度...?)找出是否将新元素添加到您的字典中。
【解决方案2】:

虽然我认为另一个答案是最优雅和正确的,但这是一种解决方法,以防更改软件架构不是一个可行的选择。

也许您可以使用时间戳列表来跟踪添加条目的时间。 因此,对于您的“redis”列表中的每个条目,您的“时间戳”列表中都会有一个相应的条目。时间戳(或其哈希)也可以用作 Redis 上的标识。您需要确保的是,对于“redis”列表中的每个条目,都会在“timestamp”列表中添加相应的时间戳。删除第一个元素时相同。

【讨论】:

  • 我实际上想到了这个解决方案,但是重置列表中的那些元素完全是新元素,所以我对时间戳的实现并不完全满意
【解决方案3】:

您也许可以使用以下课程来完成您所追求的:

from typing import List, Iterator, Iterable, Union, overload, Optional, \
    Callable, Any


class UniqueError(ValueError):
    def __init__(self):
        super().__init__('all values in a UniqueList must be distinct')
        raise self


class UniqueList(list):
    def __init__(self, iterable=()) -> None:
        super().__init__(iterable)
        self.__unique = set(self)
        if len(self) != len(self.__unique):
            UniqueError()

    def clear(self) -> None:
        super().clear()
        self.__unique.clear()

    def copy(self) -> List[Any]:
        type_self = type(self)
        instance = type_self.__new__(type_self)
        super(type_self, instance).__init__(self)
        instance.__unique = self.__unique.copy()
        return instance

    def append(self, obj: Any) -> None:
        if obj in self.__unique:
            UniqueError()
        self.__unique.add(obj)
        super().append(obj)

    def extend(self, iterable: Iterable[Any]) -> None:
        copy = list(iterable)
        if any(obj in self.__unique for obj in copy):
            UniqueError()
        super().extend(copy)

    def pop(self, index: int = ...) -> Any:
        value = super().pop(index)
        self.__unique.remove(value)
        return value

    def index(self, obj: Any, start: int = ..., stop: int = ...) -> int:
        return super().index(obj, start, stop)

    def count(self, obj: Any) -> int:
        return int(obj in self.__unique)

    def insert(self, index: int, obj: Any) -> None:
        if obj in self.__unique:
            UniqueError()
        self.__unique.add(obj)
        super().insert(index, obj)

    def remove(self, obj: Any) -> None:
        super().remove(obj)
        self.__unique.remove(obj)

    def reverse(self) -> None:
        super().reverse()

    def sort(self, *, key: Optional[Callable[[Any], Any]] = ...,
             reverse: bool = ...) -> None:
        super().sort(key=key, reverse=reverse)

    def __len__(self) -> int:
        return super().__len__()

    def __iter__(self) -> Iterator[Any]:
        return super().__iter__()

    def __str__(self) -> str:
        return super().__str__()

    def __hash__(self) -> int:
        return super().__hash__()

    @overload
    def __getitem__(self, i: int) -> Any: ...

    @overload
    def __getitem__(self, s: slice) -> List[Any]: ...

    def __getitem__(self, i: int) -> Any:
        return super().__getitem__(i)

    @overload
    def __setitem__(self, i: int, o: Any) -> None: ...

    @overload
    def __setitem__(self, s: slice, o: Iterable[Any]) -> None: ...

    def __setitem__(self, i: int, o: Any) -> None:
        current = super().__getitem__(i)
        if current == o or o in self.__unique:
            UniqueError()
        self.__unique.add(o)
        self.__unique.remove(current)
        super().__setitem__(i, o)

    def __delitem__(self, i: Union[int, slice]) -> None:
        self.__unique.remove(super().__getitem__(i))
        super().__delitem__(i)

    def __add__(self, x: List[Any]) -> List[Any]:
        copy = self.copy()
        copy += x
        return copy

    def __iadd__(self, x: Iterable[Any]) -> List[Any]:
        self.extend(x)
        return self

    def __mul__(self, n: int) -> List[Any]:
        raise NotImplementedError('multiplication is not supported')

    def __rmul__(self, n: int) -> List[Any]:
        raise NotImplementedError('multiplication is not supported')

    def __imul__(self, n: int) -> List[Any]:
        raise NotImplementedError('multiplication is not supported')

    def __contains__(self, o: object) -> bool:
        return super().__contains__(o)

    def __reversed__(self) -> Iterator[Any]:
        return super().__reversed__()

    def __gt__(self, x: List[Any]) -> bool:
        return super().__gt__(x)

    def __ge__(self, x: List[Any]) -> bool:
        return super().__ge__(x)

    def __lt__(self, x: List[Any]) -> bool:
        return super().__lt__(x)

    def __le__(self, x: List[Any]) -> bool:
        return super().__le__(x)

【讨论】:

    【解决方案4】:

    list 似乎不是合适的数据类型。首先,将所有元素与另一个元素进行比较时,非常大的列表将变得不可行,即您的排序队列的性能特征是二次的。这对您来说可能不是问题,也不能回答您的问题。

    您可能还想查看queue,它也不能回答您的问题,但可能仍然有帮助。

    另外,itertools 可能会感兴趣。

    从您的问题不清楚,您是否需要记住所有曾经访问过的字符串,或者只记住当前列表中的字符串。如前所述,要记住看到的字符串,请考虑使用set

    我的最终建议是:您可能希望将它们设置为NonePLACEHOLDER = object(),而不是删除/删除头部元素,以保留索引。

    祝你好运。

    【讨论】:

      猜你喜欢
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 2022-01-22
      • 2018-04-14
      相关资源
      最近更新 更多