値に対して複数の変数をテストする方法は?
複数の変数を整数と比較し、3文字の文字列を出力する関数を作成しようとしています。これをPythonに変換する方法があるかどうか疑問に思いました。だから、言って:
x = 0
y = 1
z = 3
mylist = []
if x or y or z == 0 :
mylist.append("c")
if x or y or z == 1 :
mylist.append("d")
if x or y or z == 2 :
mylist.append("e")
if x or y or z == 3 :
mylist.append("f")
これは次のリストを返します:
["c", "d", "f"]
このようなことは可能ですか?
回答
ブール式がどのように機能するかを誤解しています。それらは英語の文のようには機能せず、ここですべての名前について同じ比較について話していると推測します。あなたは探している:
if x == 1 or y == 1 or z == 1:
x
そして、y
(そうでない場合は、自分で評価されFalse
ている場合0
、True
そうでありません)。
タプルに対する包含テストを使用して、これを短縮できます。
if 1 in (x, y, z):
またはそれ以上:
if 1 in {x, y, z}:
を使用しset
てin
定額メンバーシップテストを利用します(左側のオペランドが何であれ、一定の時間がかかります)。
を使用するとor
、Pythonは演算子の各側を個別の式として認識します。式x or y == 1
は最初にのブールテストとして扱われx
、それがFalseの場合、式y == 1
がテストされます。
これは、演算子の優先順位によるものです。or
オペレータは、より低い優先順位有する==
後者が評価されるので、テストを最初。
ただし、そうではなく、式x or y or z == 1
が実際に(x or y or z) == 1
代わりに解釈されたとしても、これは期待どおりの動作をしません。
x or y or z
'truthy'である最初の引数に評価されFalse
ます。たとえば、数値0または空ではありません(ブール式のコンテキストでPythonがfalseと見なすものの詳細については、ブール式を参照してください)。
したがって、値の場合x = 2; y = 1; z = 0
、x or y or z
はに解決され2
ます。これは、引数の最初の真のような値であるためです。その後2 == 1
だろうFalse
にもかかわらず、y == 1
だろうTrue
。
同じことが逆数にも当てはまります。単一の変数に対して複数の値をテストします。x == 1 or 2 or 3
同じ理由で失敗します。x == 1 or x == 2 or x == 3
またはを使用しx in {1, 2, 3}
ます。
次のような辞書構造を使用すると、問題に簡単に対処できます。
x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]
Martijn Pietersが述べているように、正確で最速のフォーマットは次のとおりです。
if 1 in {x, y, z}:
if文の彼のアドバイスを使用して、あなたは今、Pythonが、前者はなかったかどうかをそれぞれの文を読みますので、別々のだろうTrue
かFalse
。といった:
if 0 in {x, y, z}:
mylist.append("c")
if 1 in {x, y, z}:
mylist.append("d")
if 2 in {x, y, z}:
mylist.append("e")
...
これは機能しますが、辞書の使用に慣れている場合(私がそこで行ったことを参照)、数値を必要な文字にマッピングする最初の辞書を作成し、forループを使用するだけでこれをクリーンアップできます。
num_to_letters = {0: "c", 1: "d", 2: "e", 3: "f"}
for number in num_to_letters:
if number in {x, y, z}:
mylist.append(num_to_letters[number])
直接書く方法x or y or z == 0
は
if any(map((lambda value: value == 0), (x,y,z))):
pass # write your logic.
しかし、私は思いません、あなたはそれが好きです。:)そしてこの方法は醜いです。
他の方法(より良い)は次のとおりです。
0 in (x, y, z)
ところで、たくさんのif
sはこのようなものとして書くことができます
my_cases = {
0: Mylist.append("c"),
1: Mylist.append("d")
# ..
}
for key in my_cases:
if key in (x,y,z):
my_cases[key]()
break
非常に怠惰な場合は、値を配列内に配置できます。といった
list = []
list.append(x)
list.append(y)
list.append(z)
nums = [add numbers here]
letters = [add corresponding letters here]
for index in range(len(nums)):
for obj in list:
if obj == num[index]:
MyList.append(letters[index])
break
数字や文字を辞書に入れて実行することもできますが、これはおそらくifステートメントよりもはるかに複雑です。それはあなたが余分な怠惰になろうとすることで得られるものです:)
もう一つ、あなたの
if x or y or z == 0:
コンパイルされますが、希望する方法ではありません。ifステートメントに変数を入れるだけの場合(例)
if b
プログラムは、変数がnullでないかどうかを確認します。上記のステートメントを書く別の方法(より理にかなっています)は
if bool(b)
Boolは、基本的にブールステートメントを検証するコマンドを実行するPythonの組み込み関数です(それが何であるかわからない場合は、今すぐifステートメントで作成しようとしているものです:))
私が見つけたもう一つの怠惰な方法は:
if any([x==0, y==0, z==0])
値が変数のセットに含まれているかどうかを確認するには、組み込みモジュールitertools
とを使用できます operator
。
例えば:
輸入:
from itertools import repeat
from operator import contains
変数を宣言します:
x = 0
y = 1
z = 3
値のマッピングを(確認したい順序で)作成します。
check_values = (0, 1, 3)
itertools
変数の繰り返しを許可するために使用します。
check_vars = repeat((x, y, z))
最後に、map
関数を使用してイテレータを作成します。
checker = map(contains, check_vars, check_values)
次に、(元の順序で)値を確認するときに、次を使用しますnext()
。
if next(checker) # Checks for 0
# Do something
pass
elif next(checker) # Checks for 1
# Do something
pass
等...
これは、以上の利点があるlambda x: x in (variables)
ためでoperator
作り付けのモジュールであり、より速く、より効率的に使用するよりもlambda
、カスタムインプレース関数を作成していました。
リストにゼロ以外(またはFalse)の値があるかどうかを確認するための別のオプション:
not (x and y and z)
同等:
not all((x, y, z))
Setはここでの良いアプローチです。なぜなら、ここでの目標は変数を順序付けるからです。パラメータの順序{z,y,x}
は{0,1,3}
何でもです。
>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']
このように、ソリューション全体はO(n)です。
ここで提供される優れた回答はすべて、元のポスターの特定の要件に集中し、if 1 in {x,y,z}
MartijnPietersによって提案されたソリューションに集中しています。
彼らが無視しているのは、質問のより広い意味
です。複数の値に対して1つの変数をテストするにはどうすればよいですか。
提供されているソリューションは、たとえば文字列を使用している場合、部分ヒットでは機能しません。
文字列「Wild」が複数の値にあるかどうかをテストします。
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
...
または
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in [x, y, z]: print (True)
...
このシナリオでは、文字列に変換するのが最も簡単です
>>> [x, y, z]
['Wild things', 'throttle it back', 'in the beginning']
>>> {x, y, z}
{'in the beginning', 'throttle it back', 'Wild things'}
>>>
>>> if "Wild" in str([x, y, z]): print (True)
...
True
>>> if "Wild" in str({x, y, z}): print (True)
...
True
ただし、で述べたように@codeforester
、次のように、このメソッドでは単語の境界が失われることに注意してください。
>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
...
True
3文字rot
はリストに組み合わせて存在しますが、個別の単語としては存在しません。「rot」のテストは失敗しますが、リスト項目の1つが「rotin hell」の場合、それも失敗します。
結果として、この方法を使用する場合は検索条件に注意し、この制限があることに注意してください。
私はこれがそれをよりよく処理すると思います:
my_dict = {0: "c", 1: "d", 2: "e", 3: "f"}
def validate(x, y, z):
for ele in [x, y, z]:
if ele in my_dict.keys():
return my_dict[ele]
出力:
print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e
ifを使用する場合は、次のelseステートメントが別の解決策です。
myList = []
aList = [0, 1, 3]
for l in aList:
if l==0: myList.append('c')
elif l==1: myList.append('d')
elif l==2: myList.append('e')
elif l==3: myList.append('f')
print(myList)
d = {0:'c', 1:'d', 2:'e', 3: 'f'}
x, y, z = (0, 1, 3)
print [v for (k,v) in d.items() if x==k or y==k or z==k]
このコードは役立つかもしれません
L ={x, y, z}
T= ((0,"c"),(1,"d"),(2,"e"),(3,"f"),)
List2=[]
for t in T :
if t[0] in L :
List2.append(t[1])
break;
以下の方法を試すことができます。この方法では、入力したい変数の数を自由に指定/入力できます。
mydict = {0:"c", 1:"d", 2:"e", 3:"f"}
mylist= []
num_var = int(raw_input("How many variables? ")) #Enter 3 when asked for input.
for i in range(num_var):
''' Enter 0 as first input, 1 as second input and 3 as third input.'''
globals()['var'+str('i').zfill(3)] = int(raw_input("Enter an integer between 0 and 3 "))
mylist += mydict[globals()['var'+str('i').zfill(3)]]
print mylist
>>> ['c', 'd', 'f']
ワンラインソリューション:
mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]
または:
mylist = ['cdef'[i] for i in range(4) if i in (x, y, z)]
たぶん、出力ビットセットの直接式が必要です。
x=0 or y=0 or z=0 is equivalent to x*y*z = 0
x=1 or y=1 or z=1 is equivalent to (x-1)*(y-1)*(z-1)=0
x=2 or y=2 or z=2 is equivalent to (x-2)*(y-2)*(z-2)=0
ビットにマッピングしましょう: 'c':1 'd':0xb10 'e':0xb100 'f':0xb1000
iscの関係(is'c '):
if xyz=0 then isc=1 else isc=0
数式https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315の場合は数学を使用します
[c]: (xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))
[d]: ((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))
..。
次のロジックでこれらの式を接続します。
- 論理
and
は方程式の二乗の合計です - 論理
or
は方程式の積です
合計を表す合計方程式があり、合計の合計式があります。
次に、sum&1はc、sum&2はd、sum&4はe、sum&5はfです。
この後、文字列要素のインデックスが準備完了文字列に対応する事前定義された配列を形成できます。
array[sum]
あなたに文字列を与えます。
Pythonで擬似コードを表現する最もPython的な方法は、次のとおりです。
x = 0
y = 1
z = 3
mylist = []
if any(v == 0 for v in (x, y, z)):
mylist.append("c")
if any(v == 1 for v in (x, y, z)):
mylist.append("d")
if any(v == 2 for v in (x, y, z)):
mylist.append("e")
if any(v == 3 for v in (x, y, z)):
mylist.append("f")
それは簡単に行うことができます
for value in [var1,var2,var3]:
li.append("targetValue")
1つの値で複数の変数をテストするには: if 1 in {a,b,c}:
1つの変数で複数の値をテストするには: if a in {1, 2, 3}:
ある種のシーザー暗号を構築しているようです。
より一般化されたアプローチはこれです:
input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]
出力
['c', 'd', 'f']
それがコードの望ましい副作用であるかどうかはわかりませんが、出力の順序は常に並べ替えられます。
これが必要な場合は、最終行を次のように変更できます。
sorted([chr(val + origo) for val in inputs])
口述なしで、この解決策を試してください:
x, y, z = 0, 1, 3
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]
そして与える:
['c', 'd', 'f']
あなたは辞書を使うことができます:
x = 0
y = 1
z = 3
list=[]
dict = {0: 'c', 1: 'd', 2: 'e', 3: 'f'}
if x in dict:
list.append(dict[x])
else:
pass
if y in dict:
list.append(dict[y])
else:
pass
if z in dict:
list.append(dict[z])
else:
pass
print list
これはあなたを助けます。
def test_fun(val):
x = 0
y = 1
z = 2
myList = []
if val in (x, y, z) and val == 0:
myList.append("C")
if val in (x, y, z) and val == 1:
myList.append("D")
if val in (x, y, z) and val == 2:
myList.append("E")
test_fun(2);
あなたはこれを団結させることができます
x = 0
y = 1
z = 3
1つの変数で。
In [1]: xyz = (0,1,3,)
In [2]: mylist = []
次のように条件を変更します。
In [3]: if 0 in xyz:
...: mylist.append("c")
...: if 1 in xyz:
...: mylist.append("d")
...: if 2 in xyz:
...: mylist.append("e")
...: if 3 in xyz:
...: mylist.append("f")
出力:
In [21]: mylist
Out[21]: ['c', 'd', 'f']
問題
複数の値をテストするためのパターンが
>>> 2 in {1, 2, 3}
True
>>> 5 in {1, 2, 3}
False
非常に読みやすく、多くの状況で機能しています。1つの落とし穴があります。
>>> 0 in {True, False}
True
でも欲しい
>>> (0 is True) or (0 is False)
False
解決
前の式の一般化の1つは、ytpillaiからの回答に基づいています。
>>> any([0 is True, 0 is False])
False
これは次のように書くことができます
>>> any(0 is item for item in (True, False))
False
この式は正しい結果を返しますが、最初の式ほど読みやすくはありません:-(