누락 된 값을 더 간결하게 찾으려면 어떻게해야합니까?
만약 다음 코드 점검 x
및 y
고유 값이다 (변수는 x
, y
, z
유일한 값을 가질 수있다 a
, b
또는 c
) 만약 그렇다면, 세트 z
제 문자 :
if x == 'a' and y == 'b' or x == 'b' and y == 'a':
z = 'c'
elif x == 'b' and y == 'c' or x == 'c' and y == 'b':
z = 'a'
elif x == 'a' and y == 'c' or x == 'c' and y == 'a':
z = 'b'
더 간결하고 읽기 쉽고 효율적인 방법으로이 작업을 수행 할 수 있습니까?
z = (set(("a", "b", "c")) - set((x, y))).pop()
귀하의 코드에서 세 가지 사례 중 하나가 유지된다고 가정합니다. 이 경우 집합 set(("a", "b", "c")) - set((x, y))
은에서 반환하는 단일 요소로 구성됩니다 pop()
.
편집 : Raymond Hettinger가 의견에서 제안했듯이 튜플 풀기를 사용하여 세트에서 단일 요소를 추출 할 수도 있습니다.
z, = set(("a", "b", "c")) - set((x, y))
이 strip
방법은 나를 위해 빠르게 실행되는 또 다른 옵션입니다.
z = 'abc'.strip(x+y) if x!=y else None
Sven의 우수한 코드는 너무 많은 작업을 수행했으며 chould는 pop () 대신 튜플 압축 해제를 사용했습니다 . 또한 x 와 y 가 구별 되는지if x != y
확인 하는 가드 를 추가 할 수도 있습니다 . 개선 된 답변은 다음과 같습니다.
# create the set just once
choices = {'a', 'b', 'c'}
x = 'a'
y = 'b'
# the main code can be used in a loop
if x != y:
z, = choices - {x, y}
다음은 상대적인 성능을 보여주기위한 타이밍 스위트와 비교 타이밍입니다.
import timeit, itertools
setup_template = '''
x = %r
y = %r
choices = {'a', 'b', 'c'}
'''
new_version = '''
if x != y:
z, = choices - {x, y}
'''
original_version = '''
if x == 'a' and y == 'b' or x == 'b' and y == 'a':
z = 'c'
elif x == 'b' and y == 'c' or x == 'c' and y == 'b':
z = 'a'
elif x == 'a' and y == 'c' or x == 'c' and y == 'a':
z = 'b'
'''
for x, y in itertools.product('abc', repeat=2):
print '\nTesting with x=%r and y=%r' % (x, y)
setup = setup_template % (x, y)
for stmt, name in zip([original_version, new_version], ['if', 'set']):
print min(timeit.Timer(stmt, setup).repeat(7, 100000)),
print '\t%s_version' % name
타이밍 결과는 다음과 같습니다.
Testing with x='a' and y='a'
0.0410830974579 original_version
0.00535297393799 new_version
Testing with x='a' and y='b'
0.0112571716309 original_version
0.0524711608887 new_version
Testing with x='a' and y='c'
0.0383319854736 original_version
0.048309803009 new_version
Testing with x='b' and y='a'
0.0175108909607 original_version
0.0508949756622 new_version
Testing with x='b' and y='b'
0.0386209487915 original_version
0.00529098510742 new_version
Testing with x='b' and y='c'
0.0259420871735 original_version
0.0472128391266 new_version
Testing with x='c' and y='a'
0.0423510074615 original_version
0.0481910705566 new_version
Testing with x='c' and y='b'
0.0295209884644 original_version
0.0478219985962 new_version
Testing with x='c' and y='c'
0.0383579730988 original_version
0.00530385971069 new_version
이러한 타이밍은 원본 버전의 성능이 다양한 입력 값에 의해 트리거되는 if 문에 따라 상당히 달라짐을 보여줍니다.
z = (set('abc') - set(x + y)).pop()
작동을 보여주는 모든 시나리오는 다음과 같습니다.
>>> (set('abc') - set('ab')).pop() # x is a/b and y is b/a
'c'
>>> (set('abc') - set('bc')).pop() # x is b/c and y is c/b
'a'
>>> (set('abc') - set('ac')).pop() # x is a/c and y is c/a
'b'
문제의 세 가지 항목이 아니었다면 "a"
, "b"
그리고 "c"
, 오히려 1
, 2
그리고 3
, 당신은 또한 이진 XOR를 사용할 수 있습니다 :
z = x ^ y
More generally, if you want to set z
to the remaining one of three numbers a
, b
and c
given two numbers x
and y
from this set, you can use
z = x ^ y ^ a ^ b ^ c
Of course you can precompute a ^ b ^ c
if the numbers are fixed.
This approach can also be used with the original letters:
z = chr(ord(x) ^ ord(y) ^ 96)
Example:
>>> chr(ord("a") ^ ord("c") ^ 96)
'b'
Don't expect anyone reading this code to immediately figure out what it means :)
I think the solution by Sven Marnach and F.J is beautiful, but it's not faster in my little test. This is Raymond's optimized version using a pre-computed set
:
$ python -m timeit -s "choices = set('abc')" \
-s "x = 'c'" \
-s "y = 'a'" \
"z, = choices - set(x + y)"
1000000 loops, best of 3: 0.689 usec per loop
This is the original solution:
$ python -m timeit -s "x = 'c'" \
-s "y = 'a'" \
"if x == 'a' and y == 'b' or x == 'b' and y == 'a':" \
" z = 'c'" \
"elif x == 'b' and y == 'c' or x == 'c' and y == 'b':" \
" z = 'a'" \
"elif x == 'a' and y == 'c' or x == 'c' and y == 'a':" \
" z = 'b'"
10000000 loops, best of 3: 0.310 usec per loop
Note that this is the worst possible input for the if
-statements since all six comparisons will have to be tried out. Testing with all values for x
and y
gives:
x = 'a', y = 'b': 0.084 usec per loop
x = 'a', y = 'c': 0.254 usec per loop
x = 'b', y = 'a': 0.133 usec per loop
x = 'b', y = 'c': 0.186 usec per loop
x = 'c', y = 'a': 0.310 usec per loop
x = 'c', y = 'b': 0.204 usec per loop
The set
-based variant shows the same performance for different inputs, but it is consistently between 2 and 8 times slower. The reason is that the if
-based variant runs much simpler code: equality tests compared to hashing.
I think both types of solutions are valuable: it's important to know that creating "complicated" data structures like sets cost you something in performance — while they give you a lot in readability and development speed. The complex data types are also much better when the code change: it's easy to extend the set-based solution to four, five, ... variables whereas the if-statements quickly turn into a maintenance nightmare.
Try this option, using dictionaries:
z = {'ab':'c', 'ba':'c', 'bc':'a', 'cb':'a', 'ac':'b', 'ca':'b'}[x+y]
Of course, if the x+y
key is not present in the map, it'll produce a KeyError
which you'll have to handle.
If the dictionary is precomputed a single time and stored for future use, the access will be much faster, since no new data structures will have to be created for each evaluation, only a string concatenation and a dictionary lookup are needed:
lookup_table = {'ab':'c', 'ba':'c', 'bc':'a', 'cb':'a', 'ac':'b', 'ca':'b'}
z = lookup_table[x+y]
z = 'a'*('a' not in x+y) or 'b'*('b' not in x+y) or 'c'
or less hackish and using Conditional Assignment
z = 'a' if ('a' not in x+y) else 'b' if ('b' not in x+y) else 'c'
but probably the dict solution is faster... you'd have to time it.
I think it should looks like that:
z = (set(("a", "b", "c")) - set((x, y))).pop() if x != y else None
Using list comprehension, assuming like others that one of the three cases in your code holds:
l = ['a', 'b', 'c']
z = [n for n in l if n not in [x,y]].pop()
Or, like in the accepted answer, taking advantage of the tuple to unpack it,
z, = [n for n in l if n not in [x,y]]
See if this works
if a not in xy
z= 'a'
if b not in xy
z='b'
if c not in xy
z='c'
참고URL : https://stackoverflow.com/questions/8792440/how-can-i-find-the-missing-value-more-concisely
'Development Tip' 카테고리의 다른 글
"연산자 bool () const"의 의미는 무엇입니까? (0) | 2020.10.16 |
---|---|
Python 프로세스 풀 비 데모닉? (0) | 2020.10.16 |
VS 2012 RC에서 사용자 유형 C # 구문 강조 표시가 다시 작동하도록하려면 어떻게해야합니까? (0) | 2020.10.15 |
부트 스트랩 중심 제목 (0) | 2020.10.15 |
선택기 'touchesBegan : withEvent :'로 메서드를 재정의하면 호환되지 않는 유형 '(NSSet, UIEvent)-> ()'가 있습니다. (0) | 2020.10.15 |