Đếm số lần xuất hiện / tần số của các phần tử mảng


215

Trong Javascript, tôi đang cố lấy một mảng giá trị số ban đầu và đếm các phần tử bên trong nó. Lý tưởng nhất, kết quả sẽ là hai mảng mới, lần đầu tiên chỉ định từng phần tử duy nhất và phần thứ hai chứa số lần mỗi phần tử xảy ra. Tuy nhiên, tôi mở các đề xuất về định dạng của đầu ra.

Ví dụ: nếu mảng ban đầu là:

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

Sau đó, hai mảng mới sẽ được tạo ra. Cái đầu tiên sẽ chứa tên của từng thành phần duy nhất:

5, 2, 9, 4

Thứ hai sẽ chứa số lần phần tử đó xảy ra trong mảng ban đầu:

3, 5, 1, 1

Bởi vì số 5 xảy ra ba lần trong mảng ban đầu, số 2 xảy ra năm lần và 9 và 4 đều xuất hiện một lần.

Tôi đã tìm kiếm rất nhiều giải pháp, nhưng dường như không có gì hiệu quả, và tất cả mọi thứ tôi đã cố gắng tự làm mình trở nên phức tạp một cách lố bịch. Bất kỳ trợ giúp sẽ được đánh giá cao!

Cảm ơn :)


8
Nếu tất cả những gì bạn cần là xem liệu một giá trị chỉ xuất hiện một lần (thay vì hai lần trở lên), bạn có thể sử dụngif (arr.indexOf(value) == arr.lastIndexOf(value))
Rodrigo

1
Chúng ta có thể sử dụng ramda.jsđể đạt được điều này một cách dễ dàng. 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).lengthsẽ trở lại 3để chỉ ra rằng có '3' fives trong mảng.
noobninja

Câu trả lời:


94

Ở đây bạn đi:

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

Bản demo trực tiếp: http://jsfiddle.net/simevidas/bnACW/

Ghi chú

Điều này thay đổi thứ tự của mảng đầu vào ban đầu bằng cách sử dụng Array.sort


24
có tác dụng phụ của việc sắp xếp mảng (tác dụng phụ là xấu), cũng là sắp xếp O(N log(N))và mức độ thanh lịch không đáng có
ninjagecko

1
@ninja Bạn thích câu trả lời nào khác?
Vidime Vidas

Trong trường hợp không có một nguyên thủy cấp cao đẹp từ thư viện của bên thứ ba, tôi thường sẽ thực hiện điều này giống như reducecâu trả lời. Tôi đã định gửi một câu trả lời như vậy trước khi tôi thấy nó đã tồn tại. Tuy nhiên, counts[num] = counts[num] ? counts[num]+1 : 1câu trả lời cũng hoạt động (tương đương với if(!result[a[i]])result[a[i]]=0câu trả lời, thanh lịch hơn nhưng ít dễ đọc hơn); câu trả lời này có thể được sửa đổi để sử dụng phiên bản "đẹp hơn" của vòng lặp for, có lẽ là vòng lặp for của bên thứ ba, nhưng tôi loại bỏ qua điều đó vì các vòng lặp dựa trên chỉ mục tiêu chuẩn đáng buồn là mặc định.
ninjagecko

2
@ninja Tôi đồng ý. Những câu trả lời là tốt hơn. Thật không may, tôi không thể không chấp nhận câu trả lời của riêng tôi.
Vidime Vidas

Đối với các mảng nhỏ, việc sắp xếp nó tại chỗ có thể nhanh hơn việc tạo ra một mảng kết hợp.
quant_dev

219

Bạn có thể sử dụng một đối tượng để giữ kết quả:

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

Vì vậy, bây giờ đối tượng đếm của bạn có thể cho bạn biết số đếm dành cho một số cụ thể:

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

Nếu bạn muốn có được một loạt các thành viên, chỉ cần sử dụng keys() chức năng

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

3
Cần phải chỉ ra rằng, Object.keys()chức năng đó chỉ được hỗ trợ trong IE9 +, FF4 +, SF5 +, CH6 + nhưng Opera không hỗ trợ nó. Tôi nghĩ rằng điểm dừng chương trình lớn nhất ở đây là IE9 + .
Robert Koritnik

19
Tương tự, tôi cũng thích counts[num] = (counts[num] || 0) + 1. Bằng cách đó bạn chỉ phải viết counts[num]hai lần thay vì ba lần trên một dòng đó.
robru

1
Đây là một câu trả lời tốt đẹp. Điều này dễ dàng được trừu tượng hóa thành một hàm chấp nhận một mảng và trả về một đối tượng 'đếm'.
bitand

Điều này đúng với ví dụ cụ thể trong câu hỏi, nhưng vì lợi ích của nhân viên Google, điều đáng nói là đây không phải luôn là một kỹ thuật an toàn để sử dụng rộng rãi hơn. Lưu trữ các giá trị dưới dạng các khóa đối tượng để đếm chúng có nghĩa là bạn đang truyền các giá trị đó thành chuỗi và sau đó đếm giá trị đó. [5, "5"]sẽ chỉ đơn giản nói rằng bạn đã có "5"hai lần. Hoặc đếm các trường hợp một số đối tượng khác nhau sẽ cho bạn biết có rất nhiều [object Object]. V.v.
Jimbo Jonny

Sau đó, làm cách nào tôi có thể lọc đối tượng được trả về để hiển thị cho tôi từ cao nhất đến thấp nhất hoặc thấp nhất đến cao nhất trên một số
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

Cảm ơn, giải pháp rất hay;) ... và để có được mảng "khóa" và "giá trị":const keys = Object.keys(a); const values = Object.values(a);
ncenerar

79

Nếu sử dụng gạch dưới hoặc lodash, đây là cách đơn giản nhất để làm:

_.countBy(array);

Như vậy mà:

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

Như được chỉ ra bởi những người khác, sau đó bạn có thể thực hiện các hàm _.keys()_.values()hàm trên kết quả để chỉ nhận được các số duy nhất và lần xuất hiện của chúng. Nhưng theo kinh nghiệm của tôi, đối tượng ban đầu dễ đối phó hơn nhiều.


55

Không sử dụng hai mảng cho kết quả, sử dụng một đối tượng:

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

Sau đó resultsẽ trông như:

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

47

Làm thế nào về một tùy chọn 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

Ví dụ này chuyển mảng đầu vào cho hàm Settạo tạo một tập hợp các giá trị duy nhất . Các cú pháp lây lan sau đó mở rộng các giá trị vào một mảng mới vì vậy chúng tôi có thể gọi mapvà dịch này vào một mảng hai chiều của [value, count]cặp - tức là cấu trúc sau:

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

Mảng mới sau đó được chuyển đến hàm Maptạo dẫn đến một đối tượng có thể lặp lại :

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

Điều tuyệt vời về một Mapđối tượng là nó bảo tồn các kiểu dữ liệu - nghĩa là aCount.get(5)sẽ trả về 3nhưng aCount.get("5")sẽ trả về undefined. Nó cũng cho phép bất kỳ giá trị / loại nào hoạt động như một khóa có nghĩa là giải pháp này cũng sẽ hoạt động với một mảng các đối tượng.


Bạn có bất kỳ câu trả lời nào được cải thiện về điều này chỉ cho một mảng đối tượng không? Tôi gặp khó khăn khi cố gắng sửa đổi nó cho một mảng đối tượng, trong đó bạn chỉ cần tạo một mảng / map / set mới trong đó bạn loại bỏ các bản sao và thêm một giá trị mới cho đối tượng, giả sử được gọi là "trùng lặpCount: value". tôi đã quản lý để loại bỏ các bản sao trong mảng các đối tượng lồng nhau của mình khỏi câu trả lời này stackoverflow.com/a/36744732
sharon gur

Setsử dụng các tham chiếu đối tượng cho tính duy nhất và không cung cấp API để so sánh các đối tượng "tương tự" . Nếu bạn muốn sử dụng phương pháp này cho một nhiệm vụ như vậy, bạn cần một số hàm giảm trung gian đảm bảo một loạt các trường hợp duy nhất. Nó không phải là hiệu quả nhất nhưng tôi đưa ra một ví dụ nhanh ở đây .
Emissary

Cảm ơn câu trả lời! nhưng tôi thực sự đã giải quyết nó một chút lilttle khác nhau. nếu bạn có thể thấy câu trả lời tôi đã thêm vào đây stackoverflow.com/a/43211561/4474900 tôi đã đưa ra ví dụ về những gì tôi đã làm. nó hoạt động tốt, trường hợp của tôi có một đối tượng phức tạp cần so sánh. không biết về hiệu quả của giải pháp của tôi mặc dù
sharon gur

8
Điều này có thể sử dụng các cấu trúc dữ liệu mới tốt đẹp nhưng có thời gian chạy trong O ( ) trong khi có rất nhiều thuật toán đơn giản ở đây giải quyết nó trong O ( n ).
raphinesse

41

Tôi nghĩ rằng đây là cách đơn giản nhất để đếm số lần xuất hiện có cùng giá trị trong mảng.

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

9
hoặc a.filter(value => !value).lengthvới cú pháp js mới
t3chb0t

Không trả lời câu hỏi.
Ry-

34

Giải pháp ES6 một dòng. Rất nhiều câu trả lời sử dụng đối tượng làm bản đồ nhưng tôi không thể thấy ai sử dụng Bản đồ thực tế

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

Sử dụng map.keys()để có được các yếu tố độc đáo

Sử dụng map.values()để có được sự xuất hiện

Sử dụng map.entries()để có được các cặp [phần tử, tần số]

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 hiện đại đạt được kết quả tốt nhất từ ​​tất cả các thế giới
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
Bất cứ ai cũng quan tâm để giải thích điều này (trước [dòng] = ++ trước [dòng] | | 1, trước)?
Souljacker

5
Các nhà điều hành dấu phẩy “đánh giá mỗi toán hạng của nó (từ trái sang phải) và trả về giá trị của toán hạng cuối cùng”, do đó gia tăng này giá trị của trước [Curr] (hoặc initialises nó để 1), sau đó trả về trước.
ChrisV

Nhưng đầu ra là một mảng?
Francesco

20

Nếu bạn ủng hộ một lót duy nhất.

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

Chỉnh sửa (6/12/2015) : Giải thích từ trong ra ngoài. CountMap là một bản đồ ánh xạ một từ với tần số của nó, mà chúng ta có thể thấy hàm ẩn danh. Việc giảm nào là áp dụng hàm với các đối số vì tất cả các phần tử mảng và CountMap được truyền dưới dạng giá trị trả về của lệnh gọi hàm cuối cùng. Tham số cuối cùng ({}) là giá trị mặc định của CountMap cho lệnh gọi hàm đầu tiên.


1
Bạn nên giải thích điều này. điều đó sẽ làm cho nó trở thành một câu trả lời tốt hơn nhiều để mọi người có thể học cách sử dụng nó trong các trường hợp sử dụng khác.
Andrew Grothe

Một lớp lót duy nhất loại bỏ các ngắt dòng thường đi theo ;, {}. ... ĐỒNG Ý. Tôi nghĩ với định nghĩa về một lớp lót, chúng ta có thể viết Trò chơi cuộc sống của Conway như là một "oneliner".
trincot

16

Phiên bản ES6 sẽ là nhiều trình giả lập (giải pháp một dòng khác)

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 }

Bản đồ thay vì Đối tượng đơn giản giúp chúng ta phân biệt các loại phần tử khác nhau, hoặc tất cả các cách đếm khác đều dựa trên các chuỗi


8

Nếu bạn đang sử dụng dấu gạch dưới, bạn có thể đi theo tuyến chức năng

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

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

vì vậy mảng đầu tiên của bạn là

_.keys(results)

và mảng thứ hai là

_.values(results)

hầu hết điều này sẽ mặc định cho các chức năng javascript gốc nếu chúng có sẵn

bản demo: http://jsfiddle.net/dAaUU/


8

Dựa trên câu trả lời của @adamse@pmandell (mà tôi upvote), trong ES6 bạn có thể làm điều đó trong một dòng :

  • Chỉnh sửa 2017 : Tôi sử dụng ||để giảm kích thước mã và làm cho nó dễ đọc hơn.

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

));


Nó có thể được sử dụng để đếm các ký tự :

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

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

));


Sẽ dễ đọc hơn nếu bạn sử dụng || 0:(r,k)=>{r[k]=(r[k]||0)+1;return r}
12Me21

Bạn có thể làm bất cứ điều gì trong một dòng trong JavaScript.
Ry-

Và tại sao nó là một điều xấu, @ Ry-?
ESL

Đôi khi nó rõ ràng hơn trong một số dòng, khác là rõ ràng hơn trong một dòng. Althoug đó là một vấn đề của "hương vị".
ESL

Ý tôi là, trong ES6, bạn có thể thực hiện điều đó trong một dòng mà áp dụng cho mọi câu trả lời và bạn cũng có thể thực hiện điều này trong ES5 trong một dòng.
Ry-

5

Đây chỉ là một cái gì đó nhẹ và dễ dàng cho mắt ...

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

Chỉnh sửa: Và vì bạn muốn tất cả các lần xuất hiện ...

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
Câu hỏi yêu cầu đếm tất cả các yếu tố.
Ry-

Ok, bỏ lỡ điều đó. Nên sửa ngay.
ElDoRado1239

5

Vì vậy, đây là cách tôi làm với một số tính năng javascript mới nhất:

Đầu tiên, giảm mảng xuống một Maptrong số đếm:

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

Bằng cách sử dụng a Map, mảng bắt đầu của bạn có thể chứa bất kỳ loại đối tượng nào và số đếm sẽ chính xác. Không có a Map, một số loại đối tượng sẽ cung cấp cho bạn số lượng lạ. Xem các Maptài liệu để biết thêm về sự khác biệt.

Điều này cũng có thể được thực hiện với một đối tượng nếu tất cả các giá trị của bạn là ký hiệu, số hoặc chuỗi:

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

Hoặc một chút fancier theo cách chức năng mà không bị đột biến, sử dụng cú pháp phá hủy và lây lan đối tượng:

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

Tại thời điểm này, bạn có thể sử dụng Map hoặc đối tượng cho số đếm của mình (và bản đồ có thể lặp lại trực tiếp, không giống như một đối tượng) hoặc chuyển đổi nó thành hai mảng.

Đối với Map:

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

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

Hoặc cho đối tượng:

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

Nếu bạn vẫn muốn hai mảng, thì bạn có thể sử dụng câu trả lời như thế này ...

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

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

Hoặc nếu bạn muốn uniqueNums là số

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

1
es6 / 7 làm cho tất cả điều này đẹp hơn nhiều. Bạn cũng có thể muốn giảm xuống Mapthay vào đó, vì nó sẽ tránh việc đánh máy bằng cách sử dụng một số làm khóa đối tượng (truyền dưới dạng chuỗi). const answer = array.reduce((a, e) => a.set(e, (a.get(e) || 0) + 1), new Map()).Bạn có thể lấy answer.keys()các khóa và answer.values()cho các giá trị dưới dạng mảng. [...answer]sẽ cung cấp cho bạn một mảng lớn với tất cả các khóa / giá trị là mảng 2d.
Josh từ Qaribou

4

Giải pháp ES6 với giảm (cố định):

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

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


Không chắc chắn làm thế nào một số đại diện cho số lượng của từng yếu tố mảng riêng biệt như câu hỏi được hỏi.
Ry-

4

Chỉnh sửa 2020 : đây là một câu trả lời khá cũ (chín năm). Mở rộng bản địa prototypesẽ luôn tạo ra cuộc thảo luận . Mặc dù tôi nghĩ rằng lập trình viên có thể tự do lựa chọn phong cách lập trình của riêng mình, đây là cách tiếp cận (hiện đại hơn) cho vấn đề mà không cần mở rộng 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; }

Câu trả lời cũ (2011): bạn có thể mở rộng Array.prototype, như thế này:


2

Giải pháp của tôi với 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)

Liên kết đến REPL.


2

Giải pháp sử dụng bản đồ với độ phức tạp thời gian 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;
}

Bản trình diễn: http://jsfiddle.net/simevidas/bnACW/


Upvote của tôi cho bạn, điều này hoạt động như bơ với độ phức tạp thời gian O (n)
Vishal Shetty


1

Sử dụng MAP, bạn có thể có 2 mảng trong đầu ra: Một mảng chứa các lần xuất hiện và một mảng khác chứa số lần xuất hiện.

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

Kiểm tra mã dưới đây.

<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

Thử cái này:

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

Tôi đã giải quyết một vấn đề tương tự trên tiền mã hóa và nghĩ ra giải pháp sau đây phù hợp với tôi.

Điều này cho số lượng cao nhất của một số nguyên trong một mảng và cũng là số nguyên. Tôi nghĩ rằng nó có thể được áp dụng cho mảng chuỗi là tốt.

Để sắp xếp đúng chuỗi, loại bỏ function(a, b){return a-b}từ bên trong sort()phần

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

Đây là một cách để đếm số lần xuất hiện bên trong một mảng các đối tượng. Nó cũng đặt nội dung của mảng đầu tiên bên trong một mảng mới để sắp xếp các giá trị sao cho thứ tự trong mảng ban đầu không bị phá vỡ. Sau đó, một hàm đệ quy được sử dụng để đi qua từng phần tử và đếm thuộc tính số lượng của từng đối tượng bên trong mảng.

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

Vô cùng lãng phí để sao chép đối tượng mỗi lần. Tạo ra một trường hợp xấu nhất bậc hai khi nó có thể là tuyến tính.
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

Câu hỏi này đã hơn 8 tuổi và rất nhiều, nhiều câu trả lời không thực sự tính đến ES6 và rất nhiều lợi thế của nó.

Có lẽ thậm chí còn quan trọng hơn khi nghĩ về hậu quả của mã của chúng tôi đối với việc quản lý bộ sưu tập / bộ nhớ rác bất cứ khi nào chúng tôi tạo các mảng bổ sung, tạo hai hoặc ba bản sao của mảng hoặc thậm chí chuyển đổi mảng thành các đối tượng. Đây là những quan sát tầm thường cho các ứng dụng nhỏ nhưng nếu quy mô là mục tiêu dài hạn thì hãy suy nghĩ kỹ về những điều này.

Nếu bạn chỉ cần một "bộ đếm" cho các loại dữ liệu cụ thể và điểm bắt đầu là một mảng (tôi giả sử bạn muốn có một danh sách theo thứ tự và tận dụng nhiều mảng thuộc tính và phương thức cung cấp), bạn có thể chỉ cần lặp qua mảng1 và điền mảng2 với các giá trị và số lần xuất hiện của các giá trị này được tìm thấy trong mảng1.

Đơn giản vậy thôi.

Ví dụ về lớp đơn giản SimpleCorer (ES6) cho lập trình hướng đối tượngthiết kế hướng đối tượng

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;

Việc gắn một hàm trong một lớp mà không có lý do gì không làm cho nó hướng đối tượng, finalListkhông có lý do gì để trở thành một mảng và điều này không có lợi thế gì so với việc thực hiện đúng cách.
Ry-

-1

Đây là một phương pháp trường học cổ điển để đếm mảng.

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

Bạn có thể sắp xếp nó trước nếu bạn muốn một kết quả theo thứ tự chữ cái, nhưng nếu bạn muốn giữ nguyên thứ tự nhập dữ liệu thì hãy thử lại. Các vòng lặp lồng nhau có thể chậm hơn một chút so với một số phương pháp khác trên trang này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.