簡體   English   中英

在Javascript數組中一起添加類似項

[英]Adding Similar Items Together in a Javascript Array

我正在嘗試遍歷一個數組,以便對總數進行分組和計數。

例如:

var farm = [['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]];

我想通過並首先看到'貓',然后添加所有貓值,然后重復其他獨特類別的過程。

最終的輸出是:

Cats (7)
Mice (2)
Dogs (5)

目前,我正試圖以這種方式實現它,但我顯然在某個地方犯了一個菜鳥錯誤。

var farm = [];
farm.push(['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]);
var animalCounter = function(array){
    var list = '';
    for(var i = 0; i<array.length; i++){
        var animalID = array[i][0];
        var animalCount = 0;
        for (var x; x<array.length; x++){
            if(animalID == array[x][0]){
                animalCount += array[x][0] - 1;
            }
            list += animalID + " (" + animalCount + ")\n";
        }

    }
    alert(list);
}
animalCounter(farm);

使用一個物體將類似的動物加在一起

var farm = [];
farm.push(['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]);

var o = {};

for (var i=farm.length; i--;) {
    var key = farm[i][0],
        val = farm[i][1];

    o[key] = key in o ? o[key] + val : val;
}

小提琴

然后很容易創建列表

for (var key in o) {
    list += key + " (" + o[key] + ")\n";
}

小提琴

你錯過了一個外層括號:

var farm = [['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]];

你擁有的東西最終會和你一樣

var farm = ['Dogs', 5];

逗號操作符做奇怪的事情, 尤其是var語句,因為,也會把個體變量聲明和初始化。

只為了傻瓜... (不太實用)

var farm = [['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]];

farm.reduce(function(a, b, i){
    var r = (i==1 ? a.slice() : a), 
        j = r.indexOf(b[0]);
    if(j >= 0){ 
        r[j+1] += b[1];
        return r;
    } else return r.concat(b); 
}).reduce(function(a, b, i){
    return i%2 ? a+' ('+b+')' : a+'\n'+b;
});

粗略的解釋:

迭代farm每個元素,將2D數組縮減為平面數組,其中每個奇數索引都是與前一個元素對應的“計數” - 注意檢查偶數索引中的“鍵”是否已存在於數組中(在哪個案例分別更新了它的數量) slice調用就在那里,以確保原始數組保持不變。 這導致數組看起來像:

    ["Cats", 7, "Mice", 2, "Dogs", 5]

這個新數組再次減少,這次將每個元素連接成一個字符串 - 格式取決於當前迭代是否具有奇數或偶數索引。

Array.reduce是未在舊的瀏覽器支持(如果這很重要),但有一個這些功能一個填充工具在MDN網站上提供。

我可能會做的有點不同:

var farm = [];
farm.push(['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]);

var animalCounter = function(array){
  var animalObject = {};
  for(var i = 0; i<array.length; i++){
    var animalID = array[i][0];
    var animalCount = array[i][1];
    if(animalObject[animalID]) {
      animalObject[animalID] += animalCount;
    } else {
      animalObject[animalID] = animalCount;
    }
  }
  return animalObject;
}

第一個函數animalCounter創建一個對象,將動物名稱映射到數組中的數字。 因此,對於您的示例,它將返回如下所示的對象:

{ 'Cats': 7, 'Mice': 2, 'Dogs': 5 }

從那里開始,一旦你擁有了這個對象,創建一個字符串就能以你喜歡的任何格式輸出這些數據是微不足道的:

var counter = animalCounter(farm);
var list = '';
for(var key in counter) {
  list += key + ': ' + counter[key] + ', ';
}
console.log(list); //=> Cats: 7, Mice: 2, Dogs: 5,

你的初始函數不起作用的原因是因為它沒有考慮到你的數組中可能有多個同一動物的實例。 如果你的原始數組是[['Cats', 7], ['Mice', 2], ['Dogs', 5]]它會沒問題,但因為你的Cats條目分為['Cats', 4], ['Cats', 3] ,你的原始代碼看到了兩個不同的動物。 注意我的功能:

if(animalObject[animalID]) {
  animalObject[animalID] += animalCount;
} else {
  animalObject[animalID] = animalCount;
}

代碼檢查動物是否已經存儲在新對象中,如果是,則遞增計數,而不是從0創建新計數器。這樣它就可以處理任何重復項。

我看到三個問題:

  1. 將animalCounter設置為等於動物的數量 - 新的動物數量取代了已經存儲在animalCounter中的任何動物,因此這里沒有添加任何內容
  2. 在循環中創建animalCounter變量 - 如果var animalCount在循環內,那么你實際上為數組的每個元素都有一個全新的變量
  3. 對所有類型的動物使用單個變量

相反,試試這個:

var farm = [];
farm.push(['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]);

var animalCounter = function (array) {
    var list = '',
        catsCount = 0,
        miceCount = 0,
        dogsCount = 0;
    for (var i = 0; i < array.length; i++) {
        var animalID = array[i][0];
        var animalCount = array[i][1];
        if (animalID === 'Cats') {
            catsCount += animalCount;
        } else if (animalID === 'Mice') {
            miceCount += animalCount;
        } else if (animalID === 'Dogs') {
            dogsCount += animalCount;
        }
    }
    list = 'Cats(' + catsCount + ') Mice(' + miceCount + ') Dogs(' + dogsCount + ')';
    alert(list);
}
animalCounter(farm);

每種動物都有單獨的變量,數組中的值被添加到正確的計數器變量上。

或者,對於更有條理的解決方案:

  1. var farm = []; farm.push(['Cats',3],['Cats',4],['Mice',2],['Dogs',5]);

    var animalCounter = function(array){var list ='',animalCounters = {}; for(var i = 0; i <array.length; i ++){var animalID = array [i] [0]; var animalCount = array [i] [1]; animalCounters [animalID] =(animalCounters [animalID] || 0)+ animalCount; }

     for (var id in animalCounters) { list += id + " (" + animalCounters[id] + ")\\n"; } alert(list); 

    } animalCounter(farm);

在此代碼中,animalCounters變量是一個對象。 JavaScript對象就像關聯數組一樣,它允許我們使用動物ID字符串作為動物總和的整數的“關鍵字”。 每種類型的動物都是animalCounters對象的屬性,其中該類動物的總和為其值。

我在這里使用了一些略顯晦澀的符號,所以我會解釋一下。

animalCounters[animalID]

這只是引用對象屬性的另一種方法。 在JavaScript中, animalCounters.CatsanimalCounters["Cats"]訪問同樣的東西。 但是,如果你不確定動物的類型是貓,你需要“貓”(或任何其他種類的動物)變量。 animalCounters["Cats"]表示法帶有一個字符串,所以你可以說這個並且它會起作用:

var animalID = "Dogs";
alert(animalCounters[animalID);// returns animalCounters.Dogs




animalCounters[animalID] = (animalCounters[animalID] || 0) + animalCount;

這里, (animalCounters[animalID] || 0)表示如果 animalCounters[animalID]已經有值,則將該值添加到animalCount否則0添加到animalCount 這是必要的,因為如果你嘗試在animalCounters[animalID]被設置為任何東西之前將animalCounters[animalID]添加到animalCount ,則添加將無法正常工作。

當你訪問某種動物的數量時,你犯了一個簡單的錯誤:

animalCount += array[x][0] - 1; 

farm[x][0]將始終返回動物的名稱,這是一個字符串,因此當嘗試從中減去1時,它將導致NaN (非數字)。

也是循環的第一個: for(var i; i<array.length; i++){ ...循環遍歷所有數組插槽,即使它們已被計數,因此貓將被計數兩次,因此貓而不是計為7將達到14。

您需要創建一個數組副本並取消已經計數的插槽。 棘手的部分是按值復制數組,因此對Temp的任何更改都不會更改服務器場(請參閱復制數組 ):

var farm = [];
farm.push(['Cats', 3], ['Cats', 4], ['Mice', 2], ['Dogs', 5]);
function countAnimals(array) {
    var Temp = [];
    var d = 0;
    //This while loop copies the array
    while (d < farm.length) {
        var s = array[d].toString();
        Temp.push(s.split(","));
        d++;
    }
    var list = "";
    var done = 0;
    while (done < array.length) {
        if(Temp[0][1] == "Done") {
            Temp.shift();
        } else {
            var animalID = Temp[0][0];
            var count = parseFloat(Temp[0][1]);
            Temp.shift();
            var i = 0;
            while (i < Temp.length) {
                if(Temp[i][0] == animalID) {
                    count = count + parseFloat(Temp[i][1]);
                    Temp[i][1] = "Done";
                }
                i++;
            }
            list = list + "\n" + animalID + "("+count+")";
        }
        done++;
    }
    alert(list);
}
countAnimals(farm);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM