Dizi öğelerinin oluşumlarını / sıklığını sayma


216

Javascript, sayı değerleri ilk dizi almak ve içindeki öğeleri saymaya çalışıyorum. İdeal olarak, sonuç, her biri benzersiz bir elemanı belirten ve ikincisi, her bir elemanın kaç kez meydana geldiğini içeren iki yeni dizi olacaktır. Ancak, çıktı biçimi hakkında önerilere açıkım.

Örneğin, ilk dizi şuysa:

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

Sonra iki yeni dizi oluşturulacaktı. Birincisi, her bir benzersiz öğenin adını içerir:

5, 2, 9, 4

İkincisi, öğenin ilk dizide kaç kez gerçekleştiğini içerir:

3, 5, 1, 1

5 sayısı ilk dizide üç kez oluştuğundan, 2 sayısı beş kez oluşur ve 9 ve 4'ün her ikisi de bir kez görünür.

Bir çözüm bulmak için çok şey araştırdım, ancak hiçbir şey işe yaramıyor ve kendim denediğim her şey gülünç derecede karmaşık oldu. Herhangi bir yardım mutluluk duyacağız!

Teşekkürler :)


8
İhtiyacınız olan tek şey bir değerin yalnızca bir kez (iki veya daha fazla kez) görünüp görünmediğini if (arr.indexOf(value) == arr.lastIndexOf(value))
Rodrigo

1
Bunu ramda.jsbaşarmak için kullanabiliriz . 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).length3dizide '3' beşlik olduğunu belirtmek için geri dönecektir .
noobninja

Yanıtlar:


94

Hadi bakalım:

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

Canlı demo: http://jsfiddle.net/simevidas/bnACW/

Not

Bu, orijinal giriş dizisinin sırasını kullanarak Array.sort


24
dizi sıralama yan etkisi vardır (yan etkileri kötü), aynı zamanda sıralama O(N log(N))ve zerafet kazanç buna değer değil
ninjagecko

1
@ninja Başka hangi cevabı tercih edersin?
Šime Vidas

Üçüncü taraf bir kütüphaneden hoş bir üst düzey ilkel olmadığında, normal olarak bunu reducecevap gibi uygularım . Zaten var olduğunu görmeden önce böyle bir cevap vermek üzereydim. Bununla birlikte counts[num] = counts[num] ? counts[num]+1 : 1cevap da işe yarıyor ( if(!result[a[i]])result[a[i]]=0daha zarif ama okunması daha kolay olan cevaba eşdeğer ); Bu cevaplar for döngüsünün "belki" bir üçüncü tarafı for-döngüsünün "güzel" bir sürümünü kullanmak için değiştirilebilir, ancak standart dizin tabanlı for-döngüler için ne yazık ki varsayılan olduğundan, bu tür göz ardı.
ninjagecko

2
@ninja katılıyorum. Bu cevaplar daha iyi. Maalesef kendi cevabımı kabul edemiyorum.
Šime Vidas

Küçük diziler için yerinde sıralama, ilişkilendirilebilir bir dizi oluşturmaktan daha hızlı olabilir.
quant_dev

219

Sonuçları tutmak için bir nesne kullanabilirsiniz:

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

Böylece, counts nesneniz size belirli bir sayı için sayımın ne olduğunu söyleyebilir:

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

Bir dizi üye almak istiyorsanız, keys()işlevleri kullanın

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

3
Bu Object.keys()fonksiyonun yalnızca IE9 +, FF4 +, SF5 +, CH6 + 'da desteklendiği, ancak Opera'nın desteklemediği belirtilmelidir. Bence buradaki en büyük şov tıpa IE9 + .
Robert Koritnik

19
Benzer şekilde, ben de severim counts[num] = (counts[num] || 0) + 1. Bu şekilde counts[num], o satırda üç kez yerine iki kez yazmanız gerekir .
robru

1
Bu güzel bir cevap. Bu, bir diziyi kabul eden ve bir 'sayım' nesnesi döndüren bir işleve kolayca alınır.
bitsand

Bu, sorudaki belirli örnek için geçerlidir, ancak googlers uğruna, bunun her zaman daha geniş kullanım için güvenli bir teknik olmadığını belirtmeye değer . Değerleri saymak için nesne anahtarları olarak depolamak, bu değerleri dizelere yayınladığınız ve daha sonra bu değeri saydığınız anlamına gelir. [5, "5"]sadece "5"iki kez olduğunu söyleyecek . Ya da bazı farklı nesnelerin örneklerini saymak size çok şey olduğunu söyleyecektir [object Object]. Vb.
Jimbo Jonny

Daha sonra bana döndürülen nesneyi bir sayının en yüksekten en düşüğe veya en düşükten en yüksek sayıya kadar göstermesi için nasıl filtreleyebilirim
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

Teşekkürler, çok güzel bir çözüm;) ... ve "anahtar" ve "değer" dizileri almak için:const keys = Object.keys(a); const values = Object.values(a);
ncenerar

79

Alt çizgi veya lodash kullanıyorsanız, bu yapılacak en basit şey:

_.countBy(array);

Öyle ki:

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

Başkaları tarafından işaret edildiği gibi, daha sonra sadece benzersiz sayıları ve bunların oluşumlarını elde etmek için sonuçtaki _.keys()ve _.values()işlevlerini yürütebilirsiniz . Ama tecrübelerime göre, orijinal nesnenin üstesinden gelmek çok daha kolay.


55

Sonuç için iki dizi kullanmayın, bir nesne kullanın:

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

Sonra şöyle resultgörünecek:

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

47

ECMAScript2015 seçeneği hakkında.

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

Bu örnek, giriş dizisini benzersiz değerlerden Setoluşan bir koleksiyon oluşturarak yapıcıya iletir. Yayılma sözdizimi Arayabileceğimiz böylece daha sonra yeni diziye bu değerleri genişletir mapve bir iki boyutlu bir dizi içine bu tercüme [value, count]çiftleri - yani aşağıdaki yapıya:

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

Yeni dizi daha sonra geçirilen Mapbir sonuçlanan yapıcı iterable nesne:

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

Bir Mapnesnenin en güzel yanı , veri türlerini koruyabilmesidir - yani aCount.get(5)geri dönecek 3ama aCount.get("5")geri dönecektir undefined. Ayrıca, herhangi bir değer / türün anahtar işlevi görmesini sağlar, bu da bu çözümün bir dizi nesne ile çalışacağı anlamına gelir.


şans eseri bunun sadece bir nesne dizisi için daha iyi bir cevabınız var mı? im sadece yinelenenleri kaldırmak için yeni bir dizi / harita / set oluşturmak ve nesne için yeni bir değer eklemek, "duplicatedCount: value" adlı diyelim. Bu cevaptan iç içe nesneler dizimdeki kopyaları kaldırmayı başardım stackoverflow.com/a/36744732
sharon gur

Setbenzersizlik için nesne referanslarını kullanır ve "benzer" nesnelerin karşılaştırılması için API sunmaz. Böyle bir görev için bu yaklaşımı kullanmak istiyorsanız, bir dizi benzersiz örneği garanti eden bir ara azaltma işlevine ihtiyacınız olacaktır. En verimli değil ama burada kısa bir örnek verdim .
Elçi

Cevap için teşekkürler! ama aslında biraz farklı bir şekilde çözdüm. Burada eklediğim cevabı görebiliyorsanız stackoverflow.com/a/43211561/4474900 yaptığım şeyin bir örneğini verdim. iyi çalışıyor, benim durumumun karşılaştırılması gereken karmaşık bir nesnesi vardı. benim çözüm verimliliğini bilmiyorum
sharon gur

8
Bu, güzel yeni veri yapıları kullanabilir, ancak O ( ) ' de çalışma zamanı vardır, burada O ( n )' de çözen birçok basit algoritma vardır .
raphinesse

41

Ben bu dizide aynı değeri olan oluşumları saymak için en basit yolu olduğunu düşünüyorum.

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

9
veya a.filter(value => !value).lengthyeni js sözdizimi ile
t3chb0t

Soruya cevap vermiyor.
Ry-

35

Bir satır ES6 çözümü. Nesneyi harita olarak kullanan birçok yanıt var, ancak gerçek bir Harita kullanan kimseyi göremiyorum

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

kullanım map.keys()Benzersiz öğeler elde etmek için

kullanım map.values() almak için

map.entries()Çiftleri almak için kullanın [eleman, frekans]

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()])


Modern Javascript tüm dünyalardan en iyisini alır
Igniter

30

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


4
Herkes bunu açıklamak isterdi (prev [curr] = ++ prev [curr] || 1, önceki)?
Souljacker

6
Virgül operatörü daha sonra önceki döner, Önceki [Curr] (ya da başlatır 1 olarak) bu artışlarla bu değeri “(soldan sağa) ve en son terimin değerini verir işlenenlerinden her değerlendirir”.
ChrisV

ama çıktı bir dizi mi?
Francesco

20

Tek bir astarı tercih ederseniz.

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

Edit (6/12/2015) : İçten dışa açıklama. countMap, bir kelimeyi anonim işlevi görebildiğimiz frekansıyla eşleyen bir haritadır. Toplam azaltma işlevi, tüm dizi öğeleri ve countMap öğesinin son işlev çağrısının dönüş değeri olarak iletildiği gibi işlevi bağımsız değişkenlerle uygulamaktır. Son parametre ({}), ilk işlev çağrısı için varsayılan countMap değeridir.


1
Bunu açıklamalısın. bu da çok daha iyi bir cevap verecek, böylece insanlar bunu diğer kullanım durumlarında nasıl kullanacaklarını öğrenebilecekler.
Andrew Grothe

Tek sadece genellikle takip edecek linebreak kaldırır astar ;, {ve }. ... TAMAM. Bence bu bir astarın tanımı ile Conway'in Hayat Oyunu'nu "oneliner" olarak yazabiliriz.
trincot

16

ES6 sürümü çok daha basit olmalı (başka bir tek çözüm)

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 }

Farklı nesne türlerini ayırt etmemize yardımcı olan düz Nesne yerine bir Harita, yoksa tüm sayımlar dizelere dayandırılır


8

Alt çizgi kullanıyorsanız işlevsel rotaya gidebilirsiniz

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

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

ilk diziniz

_.keys(results)

ve ikinci dizi

_.values(results)

bunların çoğu varsayılan olarak yerel javascript işlevlerini varsayılan olarak kullanır

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


8

Dayanarak cevap ait @adamse ve @pmandell (I upvote olan), içinde ES6 sen yapabilirsin tek satırda :

  • 2017 düzenleme : ||Kod boyutunu küçültmek ve daha okunabilir hale getirmek için kullanıyorum.

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},{})

));


Karakterleri saymak için kullanılabilir :

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

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

));


|| 0(r,k)=>{r[k]=(r[k]||0)+1;return r}
Kullanırsanız

JavaScript'te bir satırda her şeyi yapabilirsiniz.
Ry-

Ve neden bu kötü bir şey, @ Ry-?
ESL

Bazen birkaç satırda daha açık, diğeri bir satırda daha açıktır. Althoug bu bir "tat" meselesi.
ESL

Yani “ES6'da tek satırda yapabilirsiniz” her cevap için geçerlidir ve bunu ES5'te tek satırda da yapabilirsiniz.
Ry-

5

İşte gözler için hafif ve kolay bir şey ...

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

Edit: Ve tüm oluşumları istediğiniz için ...

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
Soru tüm unsurların sayılmasını istedi.
Ry-

Tamam, kaçırdım. Şimdi düzeltilmelidir.
ElDoRado1239

5

İşte en yeni javascript özellikleri ile bunu nasıl yaparım:

İlk olarak, diziyi Mapsayımlardan birine düşürün :

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

A kullanarak Map, başlangıç ​​diziniz herhangi bir nesne türü içerebilir ve sayımlar doğru olur. A olmadan Map, bazı nesne türleri size tuhaf sayımlar verecektir. Farklılıklar hakkında daha fazla bilgi için Mapdokümanlara bakın .

Bu, tüm değerleriniz semboller, sayılar veya dizeler ise bir nesne ile de yapılabilir:

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

Ya da yıkım ve nesne yayılımı sözdizimini kullanarak mutasyon olmadan fonksiyonel bir şekilde biraz daha meraklı:

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

Bu noktada, Map veya nesnesini sayımlarınız için (ve harita bir nesnenin aksine doğrudan yinelenebilir) veya iki diziye dönüştürebilirsiniz.

İçin Map:

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

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

Veya nesne için:

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

Hala iki dizi istiyorsanız , o zaman böyle bir cevap kullanabilirsiniz ...

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

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

Veya uniqueNums öğesinin sayı olmasını istiyorsanız

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

1
es6 / 7 bunu çok daha güzel yapıyor. Bunun Mapyerine, bir sayıyı nesne anahtarı olarak (dize olarak döküm) kullanmanın yazımını önleyeceğinden, bunun yerine azaltmak da isteyebilirsiniz . const answer = array.reduce((a, e) => a.set(e, (a.get(e) || 0) + 1), new Map()).Arzu alabilirsiniz answer.keys()anahtarlar için ve answer.values()diziler olarak değerler için. [...answer]2d dizileri olarak tüm anahtar / değerleri içeren büyük bir dizi verecektir.
Qaribou'dan Josh

4

İndirimli ES6 çözeltisi (sabit):

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

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


Bir sayının, sorulan soru gibi her farklı dizi öğesinin sayısını nasıl temsil ettiğinden emin değilim.
Ry-

4

Edit 2020 : Bu oldukça eski bir cevap (dokuz yıl). Yerel dili genişletmek prototypeher zaman tartışma yaratacaktır . Programcının kendi programlama stilini seçmekte özgür olduğunu düşünmeme rağmen, soruna uzatılmadan (daha modern) bir yaklaşım var 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; }

Eski (2011) yanıtı: şöyle genişletebilirsiniz Array.prototype:


2

Ramda ile çözümüm:

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)

REPL bağlantısı.


2

O (n) zaman karmaşıklığına sahip bir harita kullanarak çözüm .

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/


Sana benim oy, bu O (n) zaman karmaşıklığı ile tereyağı gibi çalışır
Vishal Shetty


1

MAP kullanarak çıktıda 2 dizi olabilir: Biri olayları, diğeri olay sayısını içerir.

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

Aşağıdaki kodu inceleyin.

<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

Bunu dene:

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

Kod yazılımlarında benzer bir sorunu çözüyordum ve benim için çalışan aşağıdaki çözümü tasarladım.

Bu, bir dizideki en büyük tamsayıyı ve tamsayının kendisini verir. Ben de dize dizisine de uygulanabileceğini düşünüyorum.

Dizeleri düzgün sıralamak için function(a, b){return a-b}, sort()bölümün içindeki

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

İşte bir nesne dizisindeki oluşumları saymanın bir yolu. Ayrıca, orijinal dizideki sıralamanın bozulmaması için değerleri sıralamak üzere ilk dizinin içeriğini yeni bir dizinin içine yerleştirir. Daha sonra, her öğenin içinden geçmek ve dizi içindeki her nesnenin miktar özelliğini saymak için özyinelemeli bir işlev kullanılır.

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

Nesneyi her seferinde kopyalamak son derece zahmetlidir. Doğrusal olabileceği zaman ikinci dereceden en kötü durum yaratır.
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

Bu soru 8 yıldan daha eski ve birçok, birçok cevap gerçekten ES6'yı ve sayısız avantajlarını dikkate almıyor.

Ek diziler oluşturduğumuzda, dizilerin çift veya üç kopyasını oluşturduğumuzda veya dizileri nesnelere dönüştürdüğümüzde çöp toplama / bellek yönetimi kodumuzun sonuçlarını düşünmek belki de daha önemlidir . Bunlar küçük uygulamalar için önemsiz gözlemlerdir, ancak ölçek uzun vadeli bir hedefse, bunları iyice düşünün.

Sadece belirli veri türleri için bir "sayaç" gerekiyorsa ve başlangıç ​​noktası bir dizi (bu nedenle bir sipariş listesi istediğiniz ve birçok özellik ve yöntem dizilerin avantajından yararlanmak varsayalım), sadece array1 üzerinden yineleyebilir ve doldurabilirsiniz dizi2'de bulunan bu değerlerin değerlerini ve yineleme sayısını içeren dizi2.

Kadar basit.

Nesne Tabanlı Programlama ve Nesne Tabanlı Tasarım için basit sınıf SimpleCounter (ES6) örneği

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;

Bir işlevi bir nedenden ötürü sınıfa sokmak nesneyi yöneltirmez, finalListbir dizi olmak için bir nedeni yoktur ve bunun düzgün bir şekilde yapılmasına göre hiçbir avantajı yoktur.
Ry-

-1

Dizileri saymak için klasik bir eski okul yöntemi.

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

Alfabetik bir sonuç istiyorsanız önce sıralayabilirsiniz, ancak verilerin girildiği sırayı korumak istiyorsanız, bunu deneyin. İç içe döngüler, bu sayfadaki diğer yöntemlerden biraz daha yavaş olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.