2015-09-26 44 views
1

我正在做一個初學者練習,找到一組數字的平均值/中值/模式/範圍。我在模式現在,發現this這對於/ in循環是如何工作的?

var store = ['1','2','2','3','4']; 
var frequency = {}; // array of frequency. 
var max = 0; // holds the max frequency. 
var result; // holds the max frequency element. 
for(var v in store) { 
     frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency. 
     if(frequency[store[v]] > max) { // is this frequency > max so far ? 
       max = frequency[store[v]]; // update max. 
       result = store[v];   // update result. 
     } 
} 

它的工作原理,但我不明白。

  • || 0在第一行做了什麼?
  • 爲什麼我不能更改密鑰名稱?

frequency["key"+store[v]]=(frequency[store[v]] || 0)+1;回報{key1: 1, key2: 1, key3: 1, key4: 1}沒有{1: 1, 2: 2, 3: 1, 4: 1},所以鍵發揮了重要作用。

  • if語句是否同時測試關鍵和值?

更換的frequency[store[v]];任何實例具有可變(var freqTest = frequency[store[v]];,循環內部或外部創建的)破壞的東西。

整個事情真的超越了我的頭腦。

+2

首先,你居然[不應該用'對...對數組in'枚舉!(https://stackoverflow.com/q/500504/1048572) – Bergi

+0

的'||如果沒有定義frequency [store [v]]'0',則0使用0作爲默認值。簡單的例子:'var x = undefined || 2'結果在'x === 2' – ray

+0

@Bergi夠公平!我會記住的。我只是想了解它是如何運作的。 – delz

回答

2

在整個邏輯的關鍵是理解這一行

frequency[store[v]]=(frequency[store[v]] || 0)+1; 

左側正被用作一個地圖爲一些數量。當v等於3時,存儲[3]返回2,從而訪問頻率[2]。

現在對於相同的迭代考慮右側。我們已經知道,

frequency[store[3]] 

解析

frequency[2] 

但什麼會這樣的回報?由於頻率[2]也將在迭代2中設置,我們將訪問迭代2中的數字。現在,讓我們來看看從一個迭代2然後得到的值:

frequency[store[2]] = (frequency[store[2]] || 0)+1 
frequency[2] = (frequency[2] || 0)+1 
frequency[2] = (null || 0)+1 
frequency[2] = 1 

唉唉......所以迭代3的值實際上是

frequency[2] = (frequency[2] || 0) + 1 
frequency[2] = (1 || 0) + 1 
frequency[2] = (1) + 1 
frequency[2] = 2 

正如你所看到的,循環使用頻率[N ]作爲地圖,並在每次找到該值時遞增該值。然後如果值更高,則該值存儲在最大值中。這是一種非常聰明的方法,可以在僅迭代列表中一次的情況下查找最高重複值。

+0

這樣寫出來非常有幫助。我希望更多的人這樣做。爲什麼它會在迭代3中選擇頻率超過0的頻率[2]? – delz

+0

這是最好的解釋,所以我會給你答案。儘管我並不完全理解它,但不是因爲你們,而是因爲我太新了。嵌套值/增量/循環是我的小腦袋太複雜了......哈哈 – delz

+0

我不使用JavaScript很多,但只要第一,因爲它是有效的左側選項被選中。如果該值未被設置,例如第一次和第二次迭代,則選擇零;否則,該值會遞增並根據最大值進行檢查。這是聰明和優化的,但可能比它需要更復雜。我必須說我喜歡算法。 – josh26757

2

什麼是| 0在第一行做?

它需要0當查找失敗時(現在還沒有一個frequency具有該名稱)的默認值,從而使地圖上一個值的首次亮相,不NaN1小號初始化(從undefined + 1)。

分配可以(並且對於初學者來說,應該)爲什麼我不能更改密鑰名擴大到

​​

你可以,你只需要到處去做。

的代碼應該多寫吸塵器這樣的:

var store = ['1','2','2','3','4']; 
var frequency = {}; // object (key-value-map) of frequency 
var max = 0; // holds the max frequency value 
var result; // holds the max frequency element name 
for (var v=0; v<store.length; v++) { 
    var key = "key" + store[v]; 
    frequency[key] = (frequency[key] || 0)+1; // increment frequency 
//        ^^^ here as well 
    if (frequency[key] > max) { // is this frequency > max so far ? 
     max = frequency[key]; // update max. 
     result = store[v];  // update result. 
//    ^^^^^^^^ alternatively use `key` also here 
    } 
} 

是if語句測試兩個鍵和值?

測試?嗯,不。它確實使用store數組中的值作爲frequency對象中的鍵。然後它將該屬性值與max進行比較。

+0

你寫的方式更清晰。頻率[鍵] =(頻率[鍵] || 0)+1;'雖然返回一個數字作爲一個值?它不會連接到'key1 = key01'或'key1 = key11'嗎? – delz

+0

'freqency [key]'是一個整數(出現的次數),而不是像'key'這樣的字符串。注意[括號表示](http://stackoverflow.com/q/4968406/1048572) - 它就像'frequency.key0 = frequency.key0 + 1;' – Bergi

+0

我想我不明白它是如何成爲頻率的.key0 = frequency.key0 + 1; || 0 + 1;',意思是'frequency.key0 = 1'。也許我需要更多的咖啡...... – delz

0

a || 0意味着如果不是不確定的,取1,否則爲0

您可以更改鍵名。

var store = ['1','2','2','3', '1', '1','4']; 
var frequency = {}; // array of frequency. 
var max = 0; // holds the max frequency. 
var result; // holds the max frequency element. 
for(var v in store) { 
    frequency['key'+store[v]]=(frequency['key'+store[v]] || 0)+1; // increment frequency. 
    if(frequency['key' + store[v]] > max) { // is this frequency > max so far ? 
      max = frequency[store[v]]; // update max. 
      result = 'key' + store[v];   // update result. 
    } 
} 
0

您詢問的有關frequency[store[v]]=(frequency[store[v]] || 0)+1的行有時稱爲OR轉移;這stack overflow question有一些很好的解釋和例子。爲了您的代碼,認爲這是我剛纔輸入到我的瀏覽器的JavaScript控制檯:

> var frequency = {}; 
<- undefined 
> frequency[0]; 
<- undefined 
> frequency[0] || 0 
<- 0 

至於你爲什麼不能更改鍵名稱,你可以,你只是還沒有改變他們「足夠的」。更改主體以用"key"+store替換每個關鍵引用將使代碼處於相同的運行狀態。

for(var v in store) { 
    // Increment the frequency of the value v 
    frequency["key"+store[v]]=(frequency["key"+store[v]] || 0)+1; 
    // is this frequency > max so far ? 
    if(frequency["key"+store[v]] > max) { 
     // If it is, we have a new, most frequently occurring number 
     // Update the max to this new highest frequency 
     max = frequency["key"+store[v]]; 
     // Update the result to the new most frequent value 
     result = store[v]; 
    } 
} 

我在代碼中添加了一些額外的註釋,以使其更清晰。

0

第一個問題: 在JavaScript中,您可以測試變量是否被定義爲布爾值。

var foo; 
if(foo) //true 
    console.log('foo is false, 0, null or not defined'); 

因此,在這種情況下,你正在測試,如果frequency已經有store[v]的元素。如果確實如此,使用,否則使用0代替,這將是一樣

var valueInFrequency = frequency[store[v]] ? frequency[store[v]] : 0; 

,然後用valueInFrequency繼續。

你的第二個問題:正如我解釋剛纔在

frequency[store[v]]=(frequency[store[v]] || 0)+1; 

你要麼通過一個提高電流值或將其設置爲0,然後通過一個提高它。如果您更改了密鑰,您將該值設置爲,但不對新值進行測試,則最終將覆蓋現有值爲0 + 1.

現在回到最後一個問題:不,噸。它使用store[v]作爲frequency的關鍵字,然後將該值與最大值進行比較。

我希望我能回答你的問題。如果有什麼還不清楚,就問!

0

作爲給定的解決方案,我提出了一個更好的解決方案來解決這個問題。

重點解決方案Array.prototype.forEach以及如果最大數量在多個項目之間共享,則獲取多個關鍵點的問題。

發生了什麼變化:

  • result現在是一個數組,因爲分配的最大計數可影響多個鍵/項。
  • for()循環被替換爲Array.prototype.forEach和允許以更緊湊的方式遍歷數組的所有元素的回調。
  • 只有max在回調中存儲。
  • 對於具有最大計數的鍵/項目是另一個必要的循環。
  • 首先從對象的按鍵與Object.keys
  • 然後遍歷鍵和檢查計數=== max和推動關鍵
  • 顯示找到的所有值。

要什麼的問題x = x || y意味着: 如果x的值是falsy(如undefinednull0-0'')的,因爲操作者Logical Or的用於y的值,。

var store = ['1', '2', '2', '3', '4', '5', '5'], 
 
    distribution = {}, 
 
    max = 0, 
 
    result = []; 
 

 
store.forEach(function (a) { 
 
    distribution[a] = (distribution[a] || 0) + 1; 
 
    if (distribution[a] > max) { 
 
     max = distribution[a];     
 
    } 
 
}); 
 
Object.keys(distribution).forEach(function (k) { 
 
    distribution[k] === max && result.push(k); 
 
}); 
 
document.write('max: ' + max + '<br>'); 
 
document.write('key/s with max count: ' + JSON.stringify(result) + '<br>'); 
 
document.write('<pre>' + JSON.stringify(distribution, 0, 4) + '</pre>');