2015-11-11 32 views
16

Vì vậy, tôi đang cố gắng tìm ra cách tạo một mảng kết hợp liệt kê các phần tử của một mảng và số lần mỗi phần tử xuất hiện mà không biết những yếu tố đó là gì trước.Cách đếm các phần tử trong một mảng, khi các phần tử không xác định

Như một ví dụ, giả sử tôi có một loạt các động vật: var animals = ['Rhino', 'Lion', 'Dog', 'Parrot', 'Parrot', 'Cat', 'Zebra', 'Rhino']

Tôi muốn tạo ra một đối tượng mà cuối cùng trông giống như:

{ 'Rhino': 2, 'Lion': 1, 'Dog': 1, 'Parrot': 2, 'Cat': 1, 'Zebra': 1 } 

Nếu tôi biết những gì các con vật trong mảng là trước, tôi có thể tất nhiên làm một cái gì đó như:

var animalsCount = {}; 

var numberOfRhinos = animals.filter(function(animal) { 
    return animal == 'Rhino' 
}).length; 

animalsCount['Rhino'] = numberOfRhinos 

để có được một đối tượng như tôi muốn. Vấn đề tất nhiên là điều này trở nên khá dài và lặp đi lặp lại tùy thuộc vào số lượng động vật. Đồng thời, nếu tôi không biết mỗi loại động vật thì tôi không thể tạo ra vật thể theo cách này. Phải có cách để làm điều này mà không biết thông tin đó, nhưng tôi bị kẹt.

Trả lời

19

Cách dễ nhất là tạo bản đồ, khởi tạo (đến 1) giá trị trong mảng dưới dạng thuộc tính trên bản đồ đó. Bạn có thể tăng giá trị của thuộc tính mỗi khi bạn thấy thuộc tính không được xác định.

function countObjs(arr) { 
 
     // So the object doesn't inherit from Object.prototype and avoids property 
 
     // name collisions 
 
     var obj = Object.create(null); 
 
     arr.forEach(function(item) { 
 
     if (obj[item]) { 
 
      obj[item]++; 
 
     } else { 
 
      obj[item] = 1; 
 
     } 
 
     }); 
 
     return obj; 
 
    } 
 
    var animals = ['Rhino', 'Lion', 'Dog', 'Parrot', 'Parrot', 'Cat', 'Zebra', 'Rhino']; 
 
    console.log(countObjs(animals)); 
 
    /* 
 
    Cat: 1 
 
    Dog: 1 
 
    Lion: 1 
 
    Parrot: 2 
 
    Rhino: 2 
 
    Zebra: 1 
 
    */

+5

Tất nhiên, sau đó một người nào đó "viết sai" 'constrictor' là' constructor' hoặc một cái gì đó và mọi thứ trở nên kỳ lạ. – user2357112

+0

@ user2357112 Tôi cho rằng bạn đang đề cập đến việc xung đột các tên thuộc tính kế thừa như 'hasOwnProperty' và' toString'? Tôi đã thêm 'Object.create (null);' để giải quyết rằng –

3

Bạn có thể lặp lại trên mỗi phần tử trong mảng, tạo một khóa trong đối tượng đếm (mảng kết hợp được gọi là chỉ gọi là các đối tượng trong JS) nếu không tồn tại và đặt nó vào 1, hoặc nếu nó tồn tại thêm vào giá trị.

animals.forEach(function(animal){ 
    var count; 

    count = animalsCount[animal]; 

    if (count){ 
    animalsCount[animal] = count + 1; 
    } else { 
    animalsCount[animal] = 1; 
    } 
}) 
+3

Tôi sẽ sử dụng 'if (animalsCount.hasOwnProperty (động vật)) {animalsCount [animal] + = 1; } else {animalsCount [animal] = 1; } 'thay thế. Nó sạch hơn rất nhiều và không yêu cầu bất kỳ biến cục bộ nào. – Toothbrush

5

Chỉ cần tạo từ điển bằng cách lặp lại máng con vật, sau đó điền lại thông qua động vật của bạn.

var animals = ['Rhino', 'Lion', 'Dog', 'Parrot', 'Parrot', 'Cat', 'Zebra', 'Rhino']; 
 
    var animals_dict={}; 
 
    for(var i=0;i<animals.length;i++){ 
 
     animals_dict[animals[i]]=0; 
 
    } 
 
    for(var i=0;i<animals.length;i++){ 
 
     animals_dict[animals[i]]=animals_dict[animals[i]]+1; 
 
    } 
 
    alert(JSON.stringify(animals_dict))

1

Bạn có thể sử dụng thư viện như lodash để có được kết quả này.

Nếu không, bạn có thể lặp lại mảng của mình. Kiểm tra xem nguyên mẫu animalsCount của bạn có chứa mục nhập động vật và giá trị gia tăng hoặc khởi tạo hay không.

2

Bạn có thể dễ dàng lấy nó trong hai mảng như dưới đây.

var animals = ['Rhino', 'Lion', 'Dog', 'Parrot', 'Parrot', 'Cat', 'Zebra', 'Rhino']; 
 

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

 
console.log(foo(animals));

Disclaimer: mảng đầu ra được thứ tự abc được sắp xếp.

+1

Bạn nên có tuyên bố từ chối trách nhiệm rằng bạn sẽ sửa đổi mảng đầu vào bằng cách sắp xếp nó. –

4

Chỉ cần lặp qua các phần tử mảng có thuộc tính và lưu trữ chúng trong đối tượng.

var animals = ['Rhino', 'Lion', 'Dog', 'Parrot', 'Parrot','Cat', 'Zebra', 'Rhino']; 
var animalsCount = {}; 

for(var i = animals.length - 1; i >=0; i--) { 
    var count = animalsCount[animals[i]]; 
    if(!count) count = 1; 
    else count++; 
    animalsCount[animals[i]] = count; 
} 

console.log(animalsCount); 
//Outupt {Rhino: 2, Zebra: 1, Cat: 1, Parrot: 2, Dog: 1…} 

//accessing particular animal count 
animalsCount['Cat'];     //outputs 1 
2

countBy trong underscore có thể đáp ứng yêu cầu của bạn.

_.countBy(animals, function(n) { return n; })

đầu ra:

{ 'Rhino': 2, 'Lion': 1, 'Dog': 1, 'Parrot': 2, 'Cat': 1, 'Zebra': 1 }

Các vấn đề liên quan