简体   繁体   English

大多数Pythonic方法在O(1)复杂度的列表中查找/检查项目?

[英]Most Pythonic way to find/check items in a list with O(1) complexity?

The problem I'm facing is finding/checking items in a list with O(1) complexity. 我面临的问题是在O(1)复杂度的列表中查找/检查项目。 The following has a complexity of O(n): 以下具有O(n)的复杂性:

'foo' in list_bar

This has a complexity of O(n) because you are using the in keyword on a list . 这具有O(n)的复杂性,因为您in list中使用了in关键字。 (Refer to Python Time Complexity ) (参考Python时间复杂度

However, if you use the in keyword on a set , it has a complexity of O(1). 但是,如果in set上使用in关键字,则其复杂度为O(1)。

The reason why I need to figure out O(1) complexity for a list, and not a set, is largely due to the need to account for duplicate items within the list. 我需要弄清楚列表的O(1)复杂性而不是集合的原因主要是由于需要考虑列表中的重复项目。 Sets do not allow for duplicates. 集不允许重复。 A decent example would be : 一个很好的例子是:

chars_available = ['h', 'e', 'l', 'o', 'o', 'z']
chars_needed = ['h', 'e', 'l', 'l', 'o']

def foo(chars_available, chars_needed):
    cpy_needed = list(chars_needed)
    for char in cpy_needed:
        if char in chars_available:
            chars_available.remove(char)
            chars_needed.remove(char)
        if not chars_needed: return True  # if chars_needed == []
    return False

foo(chars_available, chars_needed)

The example is not the focus here, so please try not to get sidetracked by it. 这个例子不是重点,所以请尽量不要偏离它。 The focus is still trying to get O(1) complexity for finding items in a list. 重点仍然是试图在列表中查找项目时获得O(1)复杂性。 How would I accomplish that pythonically? 我怎么能蟒蛇化?

(As extra credit, if you did want to show a better way of performing that operation in Python, pseudocode, or another language, I'd be happy to read it). (作为额外的功劳,如果您确实希望以Python,伪代码或其他语言显示更好的方式来执行该操作,我将很乐意阅读它)。

Thank you! 谢谢!

Edit: 编辑:

In response to Ami Tavory's answer, I learned you can't make lists faster than O(n), but the suggestion for collections.Counter() helped solve the application I was working on. 为了回应Ami Tavory的回答,我了解到你不能比O(n)更快地创建列表,但对collections.Counter()的建议帮助解决了我正在处理的应用程序。 I'm uploading my faster solution for Stack Overflow, the performance was phenomenal! 我正在为Stack Overflow上传我更快的解决方案,性能非常出色! If I'm not mistaken (correct me if I'm wrong), it should be O(1) since it involves only hashable values and no loop iteration. 如果我没有弄错(如果我错了,请纠正我),它应该是O(1),因为它只涉及可散列值而没有循环迭代。

from collections import Counter
chars_available = ['h', 'e', 'l', 'o', 'o', 'z']
chars_needed = ['h', 'e', 'l', 'l', 'o']

def foo(chars_available, chars_needed):
    counter_available = Counter(chars_available)
    counter_needed = Counter(chars_needed)
    out = counter_needed - counter_available
    if not list(out.elements()): return True
    else: return False

foo(chars_available, chars_needed)

Very fast, very pythonic! 非常快,非常pythonic! Thanks! 谢谢!

In general, it's impossible to find elements in a list in constant time. 通常,不可能在恒定时间list中找到元素。 You could hypothetically maintain both a list and a set , but updating operations will take linear time. 您可以假设维护listset ,但更新操作将花费线性时间。

You mention that your motivation is 你提到你的动机是

a list, and not a set, is largely due to the need to account for duplicate items within the list. 列表而非集合主要是由于需要考虑列表中的重复项目。 Sets do not allow for duplicates. 集不允许重复。

and ask not to focus on the example. 并要求不要专注于这个例子。 If this is your motivation, you might want to use instead of a set , a dict mapping each element to the number of its occurrences. 如果这是你的动机,你可能想要使用而不是一个set ,一个dict将每个元素映射到它的出现次数。

You might find collections.Counter useful in particular: 您可能会发现collections.Counter特别有用:

In [1]: from collections import Counter

In [2]: Counter(['h', 'e', 'l', 'o', 'o', 'z'])
Out[2]: Counter({'e': 1, 'h': 1, 'l': 1, 'o': 2, 'z': 1})

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

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