2016-06-27 10 views
0

私はPython 2.7のセットに関するチュートリアルを行っていますが、私は理解していないforループを使用して動作しています。アウトプットの違いの理由があるかもしれません。forループの動作を理解する助けが必要です

演習の目的は、forループを使用してフリーズされたセットの都市ペアで構成されたキーを含むディクショナリから、都市セットを生成することです。

データは、以下の辞書から来ている:

flight_distances = { 
    frozenset(['Atlanta', 'Chicago']): 590.0, 
    frozenset(['Atlanta', 'Dallas']): 720.0, 
    frozenset(['Atlanta', 'Houston']): 700.0, 
    frozenset(['Atlanta', 'New York']): 750.0, 
    frozenset(['Austin', 'Dallas']): 180.0, 
    frozenset(['Austin', 'Houston']): 150.0, 
    frozenset(['Boston', 'Chicago']): 850.0, 
    frozenset(['Boston', 'Miami']): 1260.0, 
    frozenset(['Boston', 'New York']): 190.0, 
    frozenset(['Chicago', 'Denver']): 920.0, 
    frozenset(['Chicago', 'Houston']): 940.0, 
    frozenset(['Chicago', 'Los Angeles']): 1740.0, 
    frozenset(['Chicago', 'New York']): 710.0, 
    frozenset(['Chicago', 'Seattle']): 1730.0, 
    frozenset(['Dallas', 'Denver']): 660.0, 
    frozenset(['Dallas', 'Los Angeles']): 1240.0, 
    frozenset(['Dallas', 'New York']): 1370.0, 
    frozenset(['Denver', 'Los Angeles']): 830.0, 
    frozenset(['Denver', 'New York']): 1630.0, 
    frozenset(['Denver', 'Seattle']): 1020.0, 
    frozenset(['Houston', 'Los Angeles']): 1370.0, 
    frozenset(['Houston', 'Miami']): 970.0, 
    frozenset(['Houston', 'San Francisco']): 1640.0, 
    frozenset(['Los Angeles', 'New York']): 2450.0, 
    frozenset(['Los Angeles', 'San Francisco']): 350.0, 
    frozenset(['Los Angeles', 'Seattle']): 960.0, 
    frozenset(['Miami', 'New York']): 1090.0, 
    frozenset(['New York', 'San Francisco']): 2570.0, 
    frozenset(['San Francisco', 'Seattle']): 680.0, 
} 

作成するテスト・リストもありチェックとして設定することを目的:コードは次のように書かれている

flying_circus_cities = [ 
    'Houston', 'Chicago', 'Miami', 'Boston', 'Dallas', 'Denver', 
    'New York', 'Los Angeles', 'San Francisco', 'Atlanta', 
    'Seattle', 'Austin' 
] 

ループは、意図した結果を生成します。

cities = set() 
for pair in flight_distances: 
    cities = cities.union(pair) 
print cities 
print "Check:", cities == set(flying_circus_cities) 

出力:

set(['Houston', 'Chicago', 'Miami', 'Boston', 'Dallas', 'Denver', 'New York', 'Los Angeles', 'San Francisco', 'Atlanta', 'Seattle', 'Austin']) 
Check: True 

私は、次のいずれかで、理解しようとしている場合しかし、私は別の結果を得ます。

cities = set() 
cities = {pair for pair in flight_distances} 
print cities 
print "Check:", cites == set(flying_circus_cities) 

または

cities = set() 
cities = cities.union(pair for pair in flight_distances) 
print cities 
print "Check:", cities == set(flying_circus_cities) 

の両方の出力:

set([frozenset(['Atlanta', 'Dallas']), frozenset(['San Francisco', 'New York']), frozenset(['Denver', 'Chicago']), frozenset(['Houston', 'San Francisco']), frozenset(['San Francisco', 'Austin']), frozenset(['Seattle', 'Los Angeles']), frozenset(['Boston', 'New York']), frozenset(['Houston', 'Atlanta']), frozenset(['New York', 'Chicago']), frozenset(['San Francisco', 'Seattle']), frozenset(['Austin', 'Dallas']), frozenset(['New York', 'Dallas']), frozenset(['Houston', 'Chicago']), frozenset(['Seattle', 'Denver']), frozenset(['Seattle', 'Chicago']), frozenset(['Miami', 'New York']), frozenset(['Los Angeles', 'Denver']), frozenset(['Miami', 'Houston']), frozenset(['San Francisco', 'Los Angeles']), frozenset(['New York', 'Denver']), frozenset(['Atlanta', 'Chicago']), frozenset(['Boston', 'Chicago']), frozenset(['Houston', 'Austin']), frozenset(['Houston', 'Los Angeles']), frozenset(['New York', 'Los Angeles']), frozenset(['Atlanta', 'New York']), frozenset(['Denver', 'Dallas']), frozenset(['Los Angeles', 'Dallas']), frozenset(['Los Angeles', 'Chicago'])]) 
Check: False 

それがでセットを生成するように意図したとおりに最初の例では、forループのペアをアンパックなぜ私は把握することはできません各都市の1つのインスタンスであり、ループを文章として書くと、frozenset([city1, city2])のペアが引き出され、代わりにセットに配置されます。

pairは、最初のインスタンスでは都市文字列を返しますが、2番目のインスタンスではfrozensetを渡す理由はわかりません。

誰かが違う行動を説明することはできますか?

注:Holtdonkopotamusで説明したように、これは異なる動作をされた理由の問題は、理解を使用するので、frozenset型のセットを作成、完全にcities変数に単一代入を行う前に、全体の辞書を評価したということでした、標準としてforループは一度に1つずつループを展開し、個々のループを個別に評価し、forループの各パスで一度に1つずつ割り当てて、渡されたペアの各インスタンスを評価しますそれ。

彼らはさらに、*-operatorを使用すると、理解の中で辞書をアンパックして、望ましい動作を生成すると説明しました。

cities = cities.union(*(set(pair) for pair in flight_distances)) 
+0

あなたのセット理解はの '.union'を行っていませんペア、すなわちすべての一意の*都市*を見つける、それは単にすべてのユニークなペアを見つけることです*。これは、最初のバージョンの 'cities = cities.union(pair)'を 'cities.add(pair)'に置き換えるのと同じです。私が知っている限り、あなたは設定された理解を使ってそれを行うことはできません(たぶん 'reduce'を使って、一行が必要な場合でも、一般的にはあなたが現在持っているものより読みにくいと考えられます)。 – jonrsharpe

+0

@jonrsharpe cities.union(飛行距離のペアのペア)で2番目のものが最初のものと同じ結果を生成しないのはなぜですか?それは、forループの外側にあるのか、理解しているのかにかかわらず、pairが同じでなければならないようです。意図した結果を生成するコードを取得し、設定された代入の前にプリントペアを置くと、それはfrozenset(['city1'、 'city2'])を出力します。 – AMR

+1

@jonrsharpeあなたは醜い 'reduce' ...' set.union(s_0、...)を使わずにそのようなセットを作ることができます、s_n) 'は、' s_0'から 's_n'までの集合を返します。 – donkopotamus

答えて

0

バージョンでは、あなたがfrozensetsetと労働組合を行う試みる間、pairは、各ループでfrozensetあるので、あなたはそれでunionを行うことができます。

最初のケースは、(各繰り返しでfrozensetと労働組合)にダウンしています:

cities = set() 
cities.union(frozenset(['Atlanta', 'Chicago'])) 
cities.union(frozenset(['Atlanta', 'Dallas'])) 
... 

だから、(数学的に)持っている:あなたの(最後の)場合

cities = {} # Empty set 
cities = {} U {'Atlanta', 'Chicago'} = {'Atlanta', 'Chicago'} 
cities = {'Atlanta', 'Chicago'} U {'Atlanta', 'Dallas'} = {'Atlanta', 'Chicago', 'Dallas'} 
... 

、あなたがいます以下の(frozensetの配列と1つの組合を)やって:

cities = set() 
cities.union([frozenset(['Atlanta', 'Chicago']), frozenset(['Atlanta', 'Dallas']), ...]) 

だから、あなたがしている:

cities = {} 
cities = {} U {{'Atlanta', 'Chicago'}, {'Atlanta', 'Dallas'}, ...} 
     = {{'Atlanta', 'Chicago'}, {'Atlanta', 'Dallas'}, ...} # Nothing disappears 

どの2つのペアが同一でないので、あなたが.union()に都市ではなく、都市のsetsetset(ペア)を渡しているので、あなたは、あなたの最初の辞書内のすべてのペアのセットを取得します。ビューのより抽象的なポイントで


、あなたが取得しようとしている。

S = {} U S1 U S2 U S3 U ... U Sn = (((({} U S1) U S2) U S3) U ...) U Sn 

付:

S = {} U {S1, S2, S3, ..., Sn} 
+0

私はあなたが作っている数学的な議論を理解しています。しかし、ループの観点からは、2番目の例では、ループ全体が実行されるまで、都市セットが割り当てられませんか? – AMR

+1

@AMRあなたの2番目の例では、1つの割り当てしかありません(最初の 'cities = set()'はここでは役に立たないので)、大きなペアの "リスト"を作成してから**。** ' () 'は、あなたが望むものではないので、それぞれのペアを' .union() '(1つずつ、または@donkopotamusバージョンを使って)に別々に送りたいと思っています。 – Holt

1

の式:

cities = set() 
cities = cities.union(pair for pair in flight_distances) 

が相互に空のセット{}の和集合を取るには、セットのセットであなたを残して

{pair_0, pair_1, pair_2, ..., pair_n} 

を設定します。これとは対照的に

、以下はあなたに流す都市のすべてを与える:

>>> set.union(*(set(pair) for pair in flight_distances)) 
{'Atlanta', 
'Austin', 
'Boston', 
'Chicago', 
'Dallas', 
'Denver', 
'Houston', 
'Los Angeles', 
'Miami', 
'New York', 
'San Francisco', 
'Seattle'} 

をここでは、プレーンセットに凍結されたセットの各キーを変換し、組合を見つけます。最初のバージョンで

+0

あなたの例は意図したセットを作りました。私は前に*記法を見ていない。それは何をして違いを生み出すのでしょうか? TY – AMR

+1

@AMR引数リストにシーケンスを展開しています([documentation](https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists)を参照)。基本的に 'f(* [a、b、c、...])'は 'f(a、b、c、...)'です。 – Holt

+0

結果に通常の 'set'インスタンスを必要としない場合は、最も簡潔なバージョンを使用することもできます:' frozenset.union(* flight_distances) 'ジェネレータ式は必要ありません! – Blckknght

関連する問題