【问题标题】:Time complexity in case of multiple "in" operator usage in a condition in pythonTime complexity in case of multiple \"in\" operator usage in a condition in python
【发布时间】:2022-12-01 22:44:57
【问题描述】:

Suppose I have 3 elements that I want to check if they are in an iterable say (str or list).

I'm going to use an str as an example now but it should be the same in the case of a list:

Assuming values to check for are 'a','b','c' and string to search in is 'abcd' saved in variable line.

There are "two" general ways of doing this:

One is to just do multiple checks

if 'a' in line and 'b' in line and 'c' in line:
    #Do something
    pass

Another is to use all

if all( sub_str in line for sub_str in ['a','b','c']):
    #Do something
    pass

I want to know if there is any time-complexity difference between the two approaches.

【问题讨论】:

  • Why don't you test it and determine that on your own? By the way, trying to define time complexity for such a small sample is probably not going to give you any reasonable results. remember time complexity is a measure of performance based on size of data being processed.
  • Probably worth noting that if you are doing a lot of membership lookups and are worried about performance you should be using a hashed data structure like a dict or set, rather than an iterable.
  • @JaredSmith Yes, I would normally use a set, I was just wondering about this in general. It's not related to any "real" code or anything,
  • @itprorh66 You are absolutely correct I should have tested it on my own! but as you said it won't make sense for such little data and I'm not aware of the implementations/optimizations that python does for these things (if any). That's why I asked this in case someone else knew about it.

标签: python


【解决方案1】:

Hard to say about time complexity, but the first is actually faster at runtime, presumably because it doesn't involve

  • a name lookup (all)
  • a function call (all)
  • a generator expression
  • a list construction (['a','b','c']) (though this may be negligible for an imported module)
    See cmets.

See for yourself:

# All found
~ $ python3 -m timeit -s "line = 'fooabc'" "'a' in line and 'b' in line and 'c' in line"
20000000 loops, best of 5: 55 nsec per loop
~ $ python3 -m timeit -s "line = 'fooabc'" "all( sub_str in line for sub_str in ['a','b','c'])"
5000000 loops, best of 5: 397 nsec per loop
# None found
~ $ python3 -m timeit -s "line = 'fooddd'" "'a' in line and 'b' in line and 'c' in line"
50000000 loops, best of 5: 25.2 nsec per loop
~ $ python3 -m timeit -s "line = 'fooddd'" "all( sub_str in line for sub_str in ['a','b','c'])"
5000000 loops, best of 5: 325 nsec per loop

【讨论】:

  • The condition _ in ['a', 'b', 'c'] is compiled to use a tuple (which is loaded as a constant), so there is no cost for creating a list.
  • Yes - dis.dis says it's LOAD_CONST 2 (('a', 'b', 'c')).
  • There is a similar special case for in of a literal set - it'll be compiled to a frozenset.
  • all short-circuits in exactly the same way the series of and operators does.
  • For n containment tests, both are O(n). The all simply has more per-test overhead for the reasons stated in the answer.
【解决方案2】:

Both are O(mn) wheremis the number of values to search andnis the length of the string.

There is no simple way to do asymptotically better. If you wanted to test for or instead of and, you could write a regex like a|b|c and it would take O(n) time to scan a string of lengthn.

But you want to test whetherallof the patterns match, which is much harder to do with a regex, although not theoretically impossible (because an intersection of regular languages is regular). An alternative approach would be something like the Aho–Corasick algorithm which can find all matches of a set of strings in O(n) time. This algorithm is not available in the standard library but there appear to be several third-party packages which implement it.

All of that said, ifmis small then I expect it is hard to get any significant improvement in actual running time compared to the simple O(mn) approach, even if other algorithms theoretically have a lower complexity.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-28
    • 2022-12-02
    • 2022-12-02
    • 2023-02-20
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多