Menghitung kejadian / frekuensi elemen array


215

Dalam Javascript, saya mencoba mengambil larik awal nilai angka dan menghitung elemen di dalamnya. Idealnya, hasilnya adalah dua array baru, yang pertama menentukan setiap elemen unik, dan yang kedua berisi berapa kali setiap elemen terjadi. Namun, saya terbuka untuk saran tentang format output.

Misalnya, jika array awal adalah:

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

Kemudian dua array baru akan dibuat. Yang pertama akan berisi nama setiap elemen unik:

5, 2, 9, 4

Yang kedua akan berisi berapa kali elemen itu terjadi dalam array awal:

3, 5, 1, 1

Karena angka 5 muncul tiga kali dalam array awal, angka 2 muncul lima kali dan 9 dan 4 keduanya muncul sekali.

Saya telah mencari banyak solusi, tetapi sepertinya tidak ada yang berhasil, dan semua yang saya coba sendiri akhirnya menjadi sangat rumit. Bantuan apa pun akan dihargai!

Terima kasih :)


8
Jika yang Anda butuhkan adalah untuk melihat apakah suatu nilai hanya muncul sekali (alih-alih dua kali atau lebih), Anda dapat menggunakanif (arr.indexOf(value) == arr.lastIndexOf(value))
Rodrigo

1
Kita dapat menggunakan ramda.jsuntuk mencapai ini dengan cara mudah. const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)
Eshwar Prasad Yaddanapudi

arr.filter(x => x===5).lengthakan kembali 3untuk menunjukkan bahwa ada 'lima' lima dalam array.
noobninja

Jawaban:


94

Ini dia:

function foo(arr) {
    var a = [], b = [], prev;

    arr.sort();
    for ( var i = 0; i < arr.length; i++ ) {
        if ( arr[i] !== prev ) {
            a.push(arr[i]);
            b.push(1);
        } else {
            b[b.length-1]++;
        }
        prev = arr[i];
    }

    return [a, b];
}

Demo langsung: http://jsfiddle.net/simevidas/bnACW/

Catatan

Ini mengubah urutan array input asli menggunakan Array.sort


24
memiliki efek samping dari mengurutkan array (efek samping buruk), juga menyortir adalah O(N log(N))dan keuntungan keanggunan tidak sepadan
ninjagecko

1
@ninja Jawaban lain mana yang Anda sukai?
Šime Vidas

Dengan tidak adanya primitif tingkat tinggi yang bagus dari perpustakaan pihak ketiga, saya biasanya akan menerapkan ini seperti reducejawabannya. Saya akan mengirimkan jawaban seperti itu sebelum saya melihatnya sudah ada. Meskipun demikian counts[num] = counts[num] ? counts[num]+1 : 1jawabannya juga bekerja (setara dengan if(!result[a[i]])result[a[i]]=0jawaban, yang lebih elegan tetapi kurang mudah dibaca); jawaban ini dapat dimodifikasi untuk menggunakan versi "lebih bagus" dari for loop, mungkin pihak ketiga untuk-loop, tapi saya agak mengabaikan itu karena for-loop berbasis indeks standar sayangnya adalah default.
ninjagecko

2
@ Ninja saya setuju. Jawaban itu lebih baik. Sayangnya saya tidak bisa menerima jawaban saya sendiri.
Šime Vidas

Untuk array kecil, mengurutkannya di tempat bisa lebih cepat daripada membuat array asosiatif.
quant_dev

219

Anda dapat menggunakan objek untuk menyimpan hasil:

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
var counts = {};

for (var i = 0; i < arr.length; i++) {
  var num = arr[i];
  counts[num] = counts[num] ? counts[num] + 1 : 1;
}

console.log(counts[5], counts[2], counts[9], counts[4]);

Jadi, sekarang objek hitungan Anda dapat memberi tahu Anda apa hitungannya untuk nomor tertentu:

console.log(counts[5]); // logs '3'

Jika Anda ingin mendapatkan array anggota, cukup gunakan keys()fungsinya

keys(counts); // returns ["5", "2", "9", "4"]

3
Harus ditunjukkan, Object.keys()fungsi itu hanya didukung di IE9 +, FF4 +, SF5 +, CH6 + tetapi Opera tidak mendukungnya. Saya pikir show stopper terbesar di sini adalah IE9 + .
Robert Koritnik

19
Demikian pula, saya juga suka counts[num] = (counts[num] || 0) + 1. Dengan begitu Anda hanya perlu menulis counts[num]dua kali alih-alih tiga kali pada satu baris di sana.
robru

1
Ini jawaban yang bagus. Ini dengan mudah diabstraksi menjadi fungsi yang menerima array dan mengembalikan objek 'jumlah'.
bitsand

Ini berlaku untuk contoh spesifik dalam pertanyaan, tetapi demi orang Google, ada baiknya menunjukkan bahwa ini tidak selalu merupakan teknik yang aman untuk penggunaan yang lebih luas. Menyimpan nilai sebagai kunci objek untuk menghitungnya berarti Anda melemparkan nilai-nilai itu ke string dan kemudian menghitung nilai itu. [5, "5"]hanya akan mengatakan Anda punya "5"dua kali. Atau menghitung contoh beberapa objek berbeda hanya akan memberi tahu Anda ada banyak [object Object]. Dll dll.
Jimbo Jonny

Lalu bagaimana saya bisa memfilter objek yang dikembalikan untuk menunjukkan angka tertinggi ke terendah, atau terendah ke tertinggi pada angka
Ryan Holton

92
var a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
  if (typeof acc[curr] == 'undefined') {
    acc[curr] = 1;
  } else {
    acc[curr] += 1;
  }

  return acc;
}, {});

// a == {2: 5, 4: 1, 5: 3, 9: 1}

39
acc[curr] ? acc[curr]++ : acc[curr] = 1;
pmandell

Terima kasih, solusi yang sangat bagus;) ... dan untuk mendapatkan array "kunci" dan "nilai":const keys = Object.keys(a); const values = Object.values(a);
ncenerar

79

Jika menggunakan garis bawah atau lodash, ini adalah hal paling sederhana untuk dilakukan:

_.countBy(array);

Seperti yang:

_.countBy([5, 5, 5, 2, 2, 2, 2, 2, 9, 4])
=> Object {2: 5, 4: 1, 5: 3, 9: 1}

Seperti yang ditunjukkan oleh orang lain, Anda kemudian dapat menjalankan _.keys()dan _.values()berfungsi pada hasil untuk mendapatkan hanya angka unik, dan kemunculannya, masing-masing. Tetapi dalam pengalaman saya, objek aslinya jauh lebih mudah untuk ditangani.


55

Jangan gunakan dua array untuk hasilnya, gunakan objek:

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]];
}

Maka resultakan terlihat seperti:

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

47

Bagaimana dengan opsi ECMAScript2015.

const a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];

const aCount = new Map([...new Set(a)].map(
    x => [x, a.filter(y => y === x).length]
));
aCount.get(5)  // 3
aCount.get(2)  // 5
aCount.get(9)  // 1
aCount.get(4)  // 1

Contoh ini meneruskan array input ke Setkonstruktor yang membuat koleksi nilai unik . The spread sintaks kemudian memperluas nilai-nilai ini ke dalam array baru sehingga kita dapat memanggil mapdan menerjemahkan ini ke dalam array dua dimensi dari [value, count]pasangan - yaitu struktur sebagai berikut:

Array [
   [5, 3],
   [2, 5],
   [9, 1],
   [4, 1]
]

Array baru kemudian diteruskan ke Mapkonstruktor yang menghasilkan objek yang dapat diubah :

Map {
    5 => 3,
    2 => 5,
    9 => 1,
    4 => 1
}

Hal yang hebat tentang suatu Mapobjek adalah ia mempertahankan tipe-data - artinya aCount.get(5)akan kembali 3tetapi aCount.get("5")akan kembali undefined. Ini juga memungkinkan untuk setiap nilai / tipe untuk bertindak sebagai makna kunci solusi ini juga akan berfungsi dengan berbagai objek.


apakah Anda punya jawaban yang ditingkatkan dari ini hanya untuk array objek? Saya mengalami masalah saat mencoba memodifikasinya untuk array objek, di mana Anda baru saja membuat array / peta / set baru tempat Anda menghapus duplikat, dan menambahkan nilai baru untuk objek tersebut, katakanlah disebut "dupatedCount: value". saya berhasil menghapus duplikat dalam array objek bersarang saya dari jawaban ini stackoverflow.com/a/36744732
sharon gur

Setmenggunakan referensi objek untuk keunikan dan tidak menawarkan API untuk perbandingan objek "serupa" . Jika Anda ingin menggunakan pendekatan ini untuk tugas semacam itu, Anda memerlukan beberapa fungsi reduksi menengah yang menjamin berbagai instance unik. Ini bukan yang paling efisien tetapi saya mengumpulkan contoh cepat di sini .
Utusan

Terima kasih atas jawabannya! tetapi saya benar-benar memecahkannya sedikit berbeda lilttle. jika Anda dapat melihat jawabannya saya tambahkan di sini stackoverflow.com/a/43211561/4474900 saya memberikan contoh dari apa yang saya lakukan. berfungsi dengan baik, kasus saya memiliki objek kompleks yang perlu dibandingkan. tidak tahu tentang efisiensi solusi saya
sharon gur

8
Ini mungkin menggunakan struktur data baru yang bagus tetapi memiliki runtime di O ( ) sementara ada banyak algoritma sederhana di sini yang menyelesaikannya di O ( n ).
raphinesse

41

Saya pikir ini adalah cara paling sederhana bagaimana menghitung kejadian dengan nilai yang sama dalam array.

var a = [true, false, false, false];
a.filter(function(value){
    return value === false;
}).length

9
atau a.filter(value => !value).lengthdengan sintaks js baru
t3chb0t

Tidak menjawab pertanyaan.
Ry-

34

Solusi ES6 satu jalur. Begitu banyak jawaban menggunakan objek sebagai peta tetapi saya tidak dapat melihat siapa pun menggunakan Peta yang sebenarnya

const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());

Gunakan map.keys()untuk mendapatkan elemen unik

Gunakan map.values()untuk mendapatkan kejadian

Gunakan map.entries()untuk mendapatkan pasangan [elemen, frekuensi]

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]

const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());

console.info([...map.keys()])
console.info([...map.values()])
console.info([...map.entries()])


Javascript modern mendapatkan yang terbaik dari semua dunia
Igniter

29

const data = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]

function count(arr) {
  return arr.reduce((prev, curr) => (prev[curr] = ++prev[curr] || 1, prev), {})
}

console.log(count(data))


3
Adakah yang mau menjelaskan ini (sebelumnya [sekarang] = ++ sebelumnya [sekarang] || 1, sebelumnya)
Pembunuh jiwa

5
The koma Operator “mengevaluasi setiap operan nya (dari kiri ke kanan) dan mengembalikan nilai dari operan terakhir”, sehingga kenaikan ini nilai prev [Curr] (atau Menginisialisasi ke 1), kemudian kembali prev.
ChrisV

tetapi apakah output array?
Francesco

20

Jika Anda menyukai satu liner.

arr.reduce(function(countMap, word) {countMap[word] = ++countMap[word] || 1;return countMap}, {});

Edit (6/12/2015) : Penjelasan dari dalam ke luar. countMap adalah peta yang memetakan sebuah kata dengan frekuensinya, yang dapat kita lihat fungsi anonimnya. Apa yang dikurangi adalah menerapkan fungsi dengan argumen karena semua elemen array dan countMap diteruskan sebagai nilai balik dari panggilan fungsi terakhir. Parameter terakhir ({}) adalah nilai default countMap untuk panggilan fungsi pertama.


1
Anda harus menjelaskan ini. itu akan membuatnya menjadi jawaban yang jauh lebih baik sehingga orang dapat belajar bagaimana menggunakannya dalam kasus penggunaan lain.
Andrew Grothe

Satu liner yang hanya menghapus linebreak yang biasanya akan mengikuti ;, {dan }. ... BAIK. Saya pikir dengan definisi one liner kita bisa menulis Game of Conway's Life sebagai "oneliner".
trincot

16

Versi ES6 harus lebih sederhana (solusi satu baris lainnya)

let arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
let acc = arr.reduce((acc, val) => acc.set(val, 1 + (acc.get(val) || 0)), new Map());

console.log(acc);
// output: Map { 5 => 3, 2 => 5, 9 => 1, 4 => 1 }

Peta bukan Objek biasa yang membantu kita membedakan berbagai jenis elemen, atau semua penghitungan didasarkan pada string


8

Jika Anda menggunakan garis bawah Anda dapat memilih rute fungsional

a = ['foo', 'foo', 'bar'];

var results = _.reduce(a,function(counts,key){ counts[key]++; return counts },
                  _.object( _.map( _.uniq(a), function(key) { return [key, 0] })))

jadi array pertama Anda adalah

_.keys(results)

dan array kedua adalah

_.values(results)

sebagian besar ini akan default ke fungsi javascript asli jika tersedia

demo: http://jsfiddle.net/dAaUU/


8

Berdasarkan jawaban dari @adamse dan @pmandell (yang saya upvote), di ES6 Anda dapat melakukannya dalam satu baris :

  • Sunting 2017 : Saya gunakan ||untuk mengurangi ukuran kode dan membuatnya lebih mudah dibaca.

var a=[7,1,7,2,2,7,3,3,3,7,,7,7,7];
alert(JSON.stringify(

a.reduce((r,k)=>{r[k]=1+r[k]||1;return r},{})

));


Ini dapat digunakan untuk menghitung karakter :

var s="ABRACADABRA";
alert(JSON.stringify(

s.split('').reduce((a, c)=>{a[c]++?0:a[c]=1;return a},{})

));


Akan lebih mudah dibaca jika Anda menggunakan || 0:(r,k)=>{r[k]=(r[k]||0)+1;return r}
12Me21

Anda dapat melakukan apa saja dalam satu baris dalam JavaScript.
Ry-

Dan mengapa itu hal yang buruk, @ Ry-?
ESL

Terkadang lebih jelas dalam beberapa baris, yang lain lebih jelas dalam satu baris. Meskipun itu masalah "rasa".
ESL

Maksud saya "di ES6 Anda dapat melakukannya dalam satu baris" berlaku untuk setiap jawaban, dan Anda juga bisa melakukan ini dalam ES5 dalam satu baris.
Ry-

5

Ini ada sesuatu yang ringan dan mudah bagi mata ...

function count(a,i){
 var result = 0;
 for(var o in a)
  if(a[o] == i)
   result++;
 return result;
}

Sunting: Dan karena Anda ingin semua kejadian ...

function count(a){
 var result = {};
 for(var i in a){
  if(result[a[i]] == undefined) result[a[i]] = 0;
  result[a[i]]++;
 }
 return result;
}

1
Pertanyaan itu menanyakan jumlah semua elemen.
Ry-

Ok, ketinggalan itu. Harus diperbaiki sekarang.
ElDoRado1239

5

Jadi, inilah cara saya melakukannya dengan beberapa fitur javascript terbaru:

Pertama, kurangi array ke Maphitungan:

let countMap = array.reduce(
  (map, value) => {map.set(value, (map.get(value) || 0) + 1); return map}, 
  new Map()
)

Dengan menggunakan Map, array awal Anda dapat berisi semua jenis objek, dan jumlah akan benar. Tanpa a Map, beberapa jenis objek akan memberi Anda jumlah aneh. Lihat Mapdokumen untuk info lebih lanjut tentang perbedaan.

Ini juga bisa dilakukan dengan objek jika semua nilai Anda adalah simbol, angka, atau string:

let countObject = array.reduce(
  (map, value) => { map[value] = (map[value] || 0) + 1; return map },
  {}
)

Atau sedikit lebih keren dengan cara fungsional tanpa mutasi, menggunakan sintaksis dan penyebaran objek sintaksis:

let countObject = array.reduce(
  (value, {[value]: count = 0, ...rest}) => ({ [value]: count + 1, ...rest }),
  {}
)

Pada titik ini, Anda dapat menggunakan Map objek atau untuk jumlah Anda (dan peta secara langsung dapat diubah, tidak seperti objek), atau mengonversinya menjadi dua array.

Untuk Map:

countMap.forEach((count, value) => console.log(`value: ${value}, count: ${count}`)

let values = countMap.keys()
let counts = countMap.values()

Atau untuk objek:

Object
  .entries(countObject) // convert to array of [key, valueAtKey] pairs
  .forEach(([value, count]) => console.log(`value: ${value}, count: ${count}`)

let values = Object.keys(countObject)
let counts = Object.values(countObject)

4
var array = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];

function countDuplicates(obj, num){
  obj[num] = (++obj[num] || 1);
  return obj;
}

var answer = array.reduce(countDuplicates, {});
// answer => {2:5, 4:1, 5:3, 9:1};

Jika Anda masih menginginkan dua array, maka Anda dapat menggunakan jawaban seperti ini ...

var uniqueNums = Object.keys(answer);
// uniqueNums => ["2", "4", "5", "9"];

var countOfNums = Object.keys(answer).map(key => answer[key]);
// countOfNums => [5, 1, 3, 1];

Atau jika Anda ingin nomor unik menjadi angka

var uniqueNums = Object.keys(answer).map(key => +key);
// uniqueNums => [2, 4, 5, 9];

1
es6 / 7 membuat ini jauh lebih baik. Anda mungkin juga ingin mengurangi menjadi Map, karena itu akan menghindari typecasting yang menggunakan angka sebagai kunci objek (casting sebagai string). const answer = array.reduce((a, e) => a.set(e, (a.get(e) || 0) + 1), new Map())Anda bisa mendapatkan answer.keys()untuk kunci, dan answer.values()untuk nilai-nilai sebagai array. [...answer]akan memberi Anda array besar dengan semua kunci / nilai sebagai array 2d.
Josh dari Qaribou

4

Solusi ES6 dengan mengurangi (diperbaiki):

const arr = [2, 2, 2, 3, 2]

const count = arr.reduce((pre, cur) => (cur === 2) ? ++pre : pre, 0)
console.log(count) // 4


Tidak yakin bagaimana satu angka mewakili jumlah setiap elemen array yang berbeda seperti pertanyaan yang diajukan.
Ry-

4

Sunting 2020 : ini adalah jawaban yang cukup lama (sembilan tahun). Memperluas asli prototypeakan selalu menghasilkan diskusi . Meskipun saya pikir programmer bebas untuk memilih gaya pemrogramannya sendiri, berikut ini adalah pendekatan (yang lebih modern) untuk masalah tanpa memperluas 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(`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; }

Jawaban lama (2011): Anda dapat memperluas Array.prototype, seperti ini:


2

Solusi saya dengan ramda:

const testArray = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]

const counfFrequency = R.compose(
  R.map(R.length),
  R.groupBy(R.identity),
)

counfFrequency(testArray)

Tautan ke REPL.


2

Solusi menggunakan peta dengan kompleksitas waktu O (n) .

var arr = [2, 2, 2, 2, 2, 4, 5, 5, 5, 9];

const countOccurrences = (arr) => {
    const map = {};
    for ( var i = 0; i < arr.length; i++ ) {
        map[arr[i]] = ~~map[arr[i]] + 1;
    }
    return map;
}

Demo: http://jsfiddle.net/simevidas/bnACW/


Suara positif saya untuk Anda, ini bekerja seperti mentega dengan kompleksitas waktu O (n)
Vishal Shetty


1

Menggunakan MAP Anda dapat memiliki 2 array di output: Satu berisi kejadian & yang lainnya berisi jumlah kejadian.

const dataset = [2,2,4,2,6,4,7,8,5,6,7,10,10,10,15];
let values = [];
let keys = [];

var mapWithOccurences = dataset.reduce((a,c) => {
  if(a.has(c)) a.set(c,a.get(c)+1);
  else a.set(c,1);
  return a;
}, new Map())
.forEach((value, key, map) => {
  keys.push(key);
  values.push(value);
});


console.log(keys)
console.log(values)


0

Lihatlah kode di bawah ini.

<html>
<head>
<script>
// array with values
var ar = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];

var Unique = []; // we'll store a list of unique values in here
var Counts = []; // we'll store the number of occurances in here

for(var i in ar)
{
    var Index = ar[i];
    Unique[Index] = ar[i];
    if(typeof(Counts[Index])=='undefined')  
        Counts[Index]=1;
    else
        Counts[Index]++;
}

// remove empty items
Unique = Unique.filter(function(){ return true});
Counts = Counts.filter(function(){ return true});

alert(ar.join(','));
alert(Unique.join(','));
alert(Counts.join(','));

var a=[];

for(var i=0; i<Unique.length; i++)
{
    a.push(Unique[i] + ':' + Counts[i] + 'x');
}
alert(a.join(', '));

</script>
</head>
<body>

</body>
</html>

0

Coba ini:

Array.prototype.getItemCount = function(item) {
    var counts = {};
    for(var i = 0; i< this.length; i++) {
        var num = this[i];
        counts[num] = counts[num] ? counts[num]+1 : 1;
    }
    return counts[item] || 0;
}

0

Saya sedang memecahkan masalah yang sama pada codewars dan menemukan solusi berikut yang bekerja untuk saya.

Ini memberikan jumlah integer tertinggi dalam array dan juga integer itu sendiri. Saya pikir itu bisa diterapkan ke array string juga.

Untuk mengurutkan String dengan benar, hapus function(a, b){return a-b}dari dalam sort()bagian itu

function mostFrequentItemCount(collection) {
    collection.sort(function(a, b){return a-b});
    var i=0;
    var ans=[];
    var int_ans=[];
    while(i<collection.length)
    {
        if(collection[i]===collection[i+1])
        {
            int_ans.push(collection[i]);
        }
        else
        {
            int_ans.push(collection[i]);
            ans.push(int_ans);
            int_ans=[];
        }
        i++;
    }

    var high_count=0;
    var high_ans;

    i=0;
    while(i<ans.length)
    {
        if(ans[i].length>high_count)
        {
            high_count=ans[i].length;
            high_ans=ans[i][0];
        }
        i++;
    }
    return high_ans;
}

0

Berikut adalah cara untuk menghitung kejadian di dalam array objek. Itu juga menempatkan isi array pertama di dalam array baru untuk mengurutkan nilai-nilai sehingga urutan dalam array asli tidak terganggu. Kemudian fungsi rekursif digunakan untuk menelusuri setiap elemen dan menghitung properti kuantitas dari setiap objek di dalam array.

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)));
}

0
function countOcurrences(arr){
    return arr.reduce((aggregator, value, index, array) => {
      if(!aggregator[value]){
        return aggregator = {...aggregator, [value]: 1};  
      }else{
        return aggregator = {...aggregator, [value]:++aggregator[value]};
      }
    }, {})
}

Sangat boros untuk menyalin objek setiap saat. Menciptakan kasus terburuk kuadratik ketika itu bisa linear.
Ry-

0
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]);
}

0

Pertanyaan ini sudah berusia lebih dari 8 tahun dan banyak, banyak jawaban tidak benar - benar memperhitungkan ES6 dan banyak keuntungannya.

Mungkin lebih penting untuk memikirkan konsekuensi dari kode kami untuk pengumpulan sampah / manajemen memori setiap kali kita membuat array tambahan, membuat salinan array dua atau tiga array atau bahkan mengubah array menjadi objek. Ini adalah pengamatan sepele untuk aplikasi kecil tetapi jika skala adalah tujuan jangka panjang maka pikirkan tentang ini, secara menyeluruh.

Jika Anda hanya memerlukan "penghitung" untuk tipe data tertentu dan titik awalnya adalah sebuah array (saya berasumsi bahwa Anda ingin daftar yang diurutkan dan mengambil keuntungan dari banyak properti dan metode yang ditawarkan array), Anda dapat dengan mudah beralih melalui array1 dan mengisi array2 dengan nilai-nilai dan jumlah kemunculan untuk nilai-nilai ini ditemukan di array1.

Sesimpel itu.

Contoh kelas sederhana SimpleCounter (ES6) untuk Pemrograman Berorientasi Objek dan Desain Berorientasi Objek

class SimpleCounter { 

    constructor(rawList){ // input array type
        this.rawList = rawList;
        this.finalList = [];
    }

    mapValues(){ // returns a new array

        this.rawList.forEach(value => {
            this.finalList[value] ? this.finalList[value]++ : this.finalList[value] = 1;
        });

        this.rawList = null; // remove array1 for garbage collection

        return this.finalList;

    }

}

module.exports = SimpleCounter;

Menempelkan fungsi di kelas tanpa alasan tidak menjadikannya berorientasi objek, finalListtidak memiliki alasan untuk menjadi array, dan ini tidak memiliki kelebihan dibandingkan melakukannya dengan benar.
Ry-

-1

Berikut adalah metode jadul klasik untuk menghitung array.

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
var counted = [], count = [];
var i = 0, j = 0, k = 0;
while (k < arr.length) {
    if (counted.indexOf(arr[k]) < 0) {
        counted[i] = arr[k];
        count[i] = 0;
        for (j = 0; j < arr.length; j++) {
            if (counted[i] == arr[j]) {
                count[i]++;
            }
        }
        i++;
    } else {
        k++;
    }
}

Anda dapat mengurutkannya terlebih dahulu jika Anda menginginkan hasil alfabet, tetapi jika Anda ingin mempertahankan urutan pemasukan data, maka cobalah. Loop bersarang mungkin sedikit lebih lambat daripada beberapa metode lain di halaman ini.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.