在Javascript中,我试图采取数字值的初始数组,并计算其中的元素。理想情况下,结果将是两个新数组,第一个数组指定每个唯一元素,第二个数组包含每个元素出现的次数。但是,我愿意听取关于输出格式的建议。

例如,如果初始数组是:

5, 5, 5, 2, 2, 2, 2, 2, 9, 4

然后将创建两个新数组。第一个将包含每个唯一元素的名称:

5, 2, 9, 4

第二个将包含该元素在初始数组中出现的次数:

3, 5, 1, 1

因为数字5在初始数组中出现了三次,数字2出现了五次,9和4都出现了一次。

我一直在寻找解决方案,但似乎没有一个可行,而且我自己尝试过的每件事最后都出奇地复杂。任何帮助都将不胜感激!

谢谢:)


当前回答

不要使用两个数组的结果,使用一个对象:

a      = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
result = { };
for(var i = 0; i < a.length; ++i) {
    if(!result[a[i]])
        result[a[i]] = 0;
    ++result[a[i]];
}

然后结果将看起来像:

{
    2: 5,
    4: 1,
    5: 3,
    9: 1
}

其他回答

编辑2020年:这是一个相当老的答案(9年)。扩展本机原型总是会引起讨论。尽管我认为程序员可以自由选择自己的编程风格,这里有一个(更现代的)方法来解决这个问题,而不需要扩展Array.prototype:

{ // create array with some pseudo random values (1 - 5) const arr = Array.from({length: 100}) .map( () => Math.floor(1 + Math.random() * 5) ); // frequencies using a reducer const arrFrequencies = arr.reduce((acc, value) => ({ ...acc, [value]: acc[value] + 1 || 1}), {} ) console.log(arrFrequencies); console.log(`Value 4 occurs ${arrFrequencies[4]} times in arrFrequencies`); // bonus: restore Array from frequencies const arrRestored = Object.entries(arrFrequencies) .reduce( (acc, [key, value]) => acc.concat(Array(value).fill(+key)), [] ); console.log(arrRestored.join()); } .as-console-wrapper { top: 0; max-height: 100% !important; }

旧的(2011年)答案是:你可以扩展Array。原型,像这样:

{ Array.prototype.frequencies = function() { var l = this.length, result = { all: [] }; while (l--) { result[this[l]] = result[this[l]] ? ++result[this[l]] : 1; } // all pairs (label, frequencies) to an array of arrays(2) for (var l in result) { if (result.hasOwnProperty(l) && l !== 'all') { result.all.push([l, result[l]]); } } return result; }; var freqs = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].frequencies(); console.log(`freqs[2]: ${freqs[2]}`); //=> 5 // or var freqs = '1,1,2,one,one,2,2,22,three,four,five,three,three,five' .split(',') .frequencies(); console.log(`freqs.three: ${freqs.three}`); //=> 3 // Alternatively you can utilize Array.map: Array.prototype.frequencies = function() { var freqs = { sum: 0 }; this.map(function(a) { if (!(a in this)) { this[a] = 1; } else { this[a] += 1; } this.sum += 1; return a; }, freqs); return freqs; } } .as-console-wrapper { top: 0; max-height: 100% !important; }

如果你喜欢单线。

加勒比海盗。reduce(function(countMap, word) {countMap[word] = ++countMap[word] || 1;return countMap}, {});

编辑(6/12/2015): 由内而外的解释。 countMap是一个映射一个单词的频率的映射,我们可以看到匿名函数。reduce所做的是应用带有参数的函数作为所有数组元素,并将countMap作为最后一次函数调用的返回值传递。最后一个参数({})是第一次函数调用时countMap的默认值。

var aa = [1,3,5,7,3,2,4,6,8,1,3,5,5,2,0,6,5,9,6,3,5,2,5,6,8];
var newArray = {};
for(var element of aa){
  if(typeof newArray[element] === 'undefined' || newArray[element] === null){
    newArray[element] = 1;
  }else{
    newArray[element] +=1;
  }
}

for ( var element in newArray){
  console.log( element +" -> "+ newArray[element]);
}

下面是一种计算对象数组中出现次数的方法。它还将第一个数组的内容放在一个新数组中,以便对值进行排序,这样原始数组中的顺序就不会被打乱。然后使用递归函数遍历每个元素并计算数组中每个对象的quantity属性。

var big_array = [
  { name: "Pineapples", quantity: 3 },
  { name: "Pineapples", quantity: 1 },
  { name: "Bananas", quantity: 1 },
  { name: "Limes", quantity: 1 },
  { name: "Bananas", quantity: 1 },
  { name: "Pineapples", quantity: 2 },
  { name: "Pineapples", quantity: 1 },
  { name: "Bananas", quantity: 1 },
  { name: "Bananas", quantity: 1 },
  { name: "Bananas", quantity: 5 },
  { name: "Coconuts", quantity: 1 },
  { name: "Lemons", quantity: 2 },
  { name: "Oranges", quantity: 1 },
  { name: "Lemons", quantity: 1 },
  { name: "Limes", quantity: 1 },
  { name: "Grapefruit", quantity: 1 },
  { name: "Coconuts", quantity: 5 },
  { name: "Oranges", quantity: 6 }
];

function countThem() {
  var names_array = [];
  for (var i = 0; i < big_array.length; i++) {
    names_array.push( Object.assign({}, big_array[i]) );
  }

  function outerHolder(item_array) {
    if (item_array.length > 0) {
      var occurrences = [];
      var counter = 0;
      var bgarlen = item_array.length;
      item_array.sort(function(a, b) { return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0); });

      function recursiveCounter() {
        occurrences.push(item_array[0]);
        item_array.splice(0, 1);
        var last_occurrence_element = occurrences.length - 1;
        var last_occurrence_entry = occurrences[last_occurrence_element].name;
        var occur_counter = 0;
        var quantity_counter = 0;
        for (var i = 0; i < occurrences.length; i++) {
          if (occurrences[i].name === last_occurrence_entry) {
            occur_counter = occur_counter + 1;
            if (occur_counter === 1) {
              quantity_counter = occurrences[i].quantity;
            } else {
              quantity_counter = quantity_counter + occurrences[i].quantity;
            }
          }
        }

        if (occur_counter > 1) {
          var current_match = occurrences.length - 2;
          occurrences[current_match].quantity = quantity_counter;
          occurrences.splice(last_occurrence_element, 1);
        }

        counter = counter + 1;

        if (counter < bgarlen) {
          recursiveCounter();
        }
      }

      recursiveCounter();

      return occurrences;
    }
  }
  alert(JSON.stringify(outerHolder(names_array)));
}

给定下面提供的数组:

const array = [ 'a', 'b', 'b', 'c', 'c', 'c' ];

你可以使用这个简单的一行代码来生成一个哈希映射,将一个键链接到它在数组中出现的次数:

const hash = Object.fromEntries([ ...array.reduce((map, key) => map.set(key, (map.get(key) || 0) + 1), new Map()) ]);
// { a: 1, b: 2, c: 3 }

扩展和解释:

// first, we use reduce to generate a map with values and the amount of times they appear
const map = array.reduce((map, key) => map.set(key, (map.get(key) || 0) + 1), new Map())

// next, we spread this map into an array
const table = [ ...map ];

// finally, we use Object.fromEntries to generate an object based on this entry table
const result = Object.fromEntries(table);

这个数组归功于@corashina。减少代码