2016-11-13 71 views
1

我有這段代碼。計數器裏面的斯卡拉理解

for { 
    country <- getCountryList 
    city <- getCityListForCountry(country) 
    person <- getPersonListForCity(person) 
} {...} 

當我們運行這段代碼,我們需要有這每遞增執行一次循環,循環的主體內的計數器。這個計數器需要顯示每個國家處理的人數。因此,每次我們開始爲新的國家執行循環時,它必須重置爲0。

我試圖

for { 
    country <- getCountryList 
    counterPerCountry = 0 
    city <- getCityListForCountry(country) 
    person <- getPersonListForCity(city) 
} {counterPerCountry = counterPerCountry + 1; ...} 

但這說,我試圖重新分配一個值VAL。

所以我試圖

var counterPerCountry = 0 
for { 
    country <- getCountryList 
    counterPerCountry = 0 
    city <- getCityListForCountry(country) 
    person <- getPersonListForCity(city) 
} {counterPerCountry = counterPerCountry + 1; ...} 

也試過

for { 
    country <- getCountryList 
    var counterPerCountry = 0 
    city <- getCityListForCountry(country) 
    person <- getPersonListForCity(city) 
} {counterPerCountry = counterPerCountry + 1; ...} 
+0

循環中計數器的用途是什麼?你能不能做一些像'counter < - 1 getList1.length'? –

+0

好的。將list1視爲國家。列表2爲城市,列表3爲人。櫃檯需要計算每個國家處理的人數。所以每次我們選擇一個新的國家(從​​名單1)我們需要重置櫃檯。每次循環迭代時,計數器都必須遞增,因爲我們使用計數器顯示處理的狀態。 –

+0

好的,計數器也需要從1到1。如果是這樣,我認爲我上面的評論提供了所需的語法... –

回答

3

在這裏,理解似乎不是一個自然的選擇。但是如果你將理解轉化爲底層操作,我認爲你可以得到一個解決方案,雖然它不像可理解的那樣可讀,但可以與Scala的函數式樣一起工作,並避免可變變量。我沿着這種思路的東西:

getCountryList flatMap (country => 
    (getCityListForCountry(country) flatMap (city => 
    getPersonListForCity(city)) 
).zipWithIndex 
) 

這應該產生的(人指數)元組列表,其中索引是從零開始的每個國家。

內部部分可以變回理解,但我不確定這是否會提高可讀性。

2

我不認爲換理解允許這個自然。你必須做點有趣的方式。這是一種方法。

var counter = 0 

for { 
    country <- getCountryList.map { elem => counter = 0; elem } 
    city <- getCityForCountry(country) 
    person <- getPersonForCity(person) 
} { 
    counter + 1 
    //do something else here 
} 

,或者使用功能爲每個國家採用了模塊化

var counter = 0 

def reset(): Unit = counter = 0 

for { 
    country <- getCountryList 
    _ = reset() 
    city <- getCityForCountry(country) 
    person <- getPersonForCity(person) 
} { 
    counter + 1 
    //do something else here 
} 

人民

val peoplePerCountry = 
for { 
    country <- getCountryList 
    cities = getCityForCountry(country) 
    city <- cities 
    persons = getPersonForCity(person) 
} yield (country -> (cities.length * persons.length)) 

代碼返回按該國

以上的,理解國家的名單,人員是答案,你不必採取反措施。這功能和乾淨。沒有可變狀態。

2

如果你只是想弄清楚如何將換修真內科學賦值給一個var,這裏有一個解決方案:

var counter = 0 
for { 
    a <- getList1 
    _ = {counter = 0} 
    b <- getList2(a) 
    c <- getList3(b) 
} { 
    counter = counter + 1 
    ... 
} 

如果你實際上是試圖算多少人在一個國家,你說這是人在一個城市的時間在全國多個城市的數數 - 那麼它歸結爲簡單的算術:我@pamu同意,換

for { 
    country <- getCountryList 
    cities = getCityListForCountry(country) 
    city <- cities 
    persons = getPersonListForCity(person) 
    personsPerCountry = cities.length * persons.length 
    person <- persons 
} {...} 
+0

那麼有沒有可能的非髒解決方案? –

+0

@KnowsNotMuch我更新了我的答案 –

1

還有一個方法,如果你唯一需要的是實際的總和會是這樣小巧而實用,例如:

getCountryList.map(country => //-- for each country 
    (country, //-- return country, and ... 
    getCityListForCountry(country).map (city => //-- the sum across cities 
     getPersonListForCity(city).length //-- of the number of people in that city 
    ).sum 
) 
) 

這與人在每個國家的一些國家的元組的列表。我喜歡將map作爲「默認」循環,在過去我會使用for。我發現索引值是很少需要的。在另一個答案中提到的zipWithIndex方法可以使用索引值。