2013-02-13 70 views
5

Tôi có 'bảng' gồm hai cột được biểu diễn dưới dạng một mảng. Cột đầu tiên là những con số từ 1 đến 20 và họ là nhãn, cột thứ hai là các giá trị tương ứng (giây):JS tính trung bình của các phần tử giống nhau trong mảng 2d

my_array = [ [ 3,4,5,3,4,5,2 ],[ 12,14,16,11,12,10,20 ] ]; 

Tôi cần giá trị trung bình (trung bình) cho mỗi nhãn:

my_mean_array = [ [ 2,3,4,5 ],[ 20/1, (12+11)/2, (14+12)/2, (16+10)/2 ] ]; 
// edit: The mean should be a float - the notion above is just for clarification. 
// Also the number 'labels' should remain as numbers/integers. 

thử của tôi:

var a = my_array[0]; 
var b = my_array[1]; 
m = []; 
n = []; 
for(var i = 0; a.length; i++){ 
    m[ a[i] ] += b[i]; // accumulate the values in the corresponding place 
    n[ a[i] ] += 1; // count the occurences 
} 
var o = []; 
var p = []; 
o = m/n; 
p.push(n); 
p.push(o); 

Trả lời

3

Làm thế nào về vấn đề này (có nguồn gốc JS, sẽ không phá vỡ trên các trình duyệt cũ):

function arrayMean(ary) { 
    var index = {}, i, label, value, result = [[],[]]; 

    for (i = 0; i < ary[0].length; i++) { 
    label = ary[0][i]; 
    value = ary[1][i]; 
    if (!(label in index)) { 
     index[label] = {sum: 0, occur: 0}; 
    } 
    index[label].sum += value; 
    index[label].occur++; 
    } 
    for (i in index) { 
    if (index.hasOwnProperty(i)) { 
     result[0].push(parseInt(i, 10)); 
     result[1].push(index[i].occur > 0 ? index[i].sum/index[i].occur : 0); 
    } 
    } 
    return result; 
} 

FWIW, nếu bạn muốn fancy tôi đã tạo ra một số cách khác để làm điều đó. Chúng phụ thuộc vào các thư viện bên ngoài và rất có thể là một thứ tự độ trễ chậm hơn so với một giải pháp gốc. Nhưng họ đẹp hơn để xem.

Nó có thể trông như thế này, với underscore.js:

function arrayMeanUnderscore(ary) { 
    return _.chain(ary[0]) 
    .zip(ary[1]) 
    .groupBy(function (item) { return item[0]; }) 
    .reduce(function(memo, items) { 
     var values = _.pluck(items, 1), 
      toSum = function (a, b) { return a + b; }; 

     memo[0].push(items[0][0]); 
     memo[1].push(_(values).reduce(toSum)/values.length); 
     return memo; 
    }, [[], []]) 
    .value(); 
} 

// -------------------------------------------- 

arrayMeanUnderscore([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]); 
// -> [[2,3,4,5], [20,11.5,13,13]] 

hay như thế này, với thực sự vĩ đại linq.js (v2.2 Tôi đã sử dụng):

function arrayMeanLinq(ary) { 
    return Enumerable.From(ary[0]) 
    .Zip(ary[1], "[$, $$]") 
    .GroupBy("$[0]") 
    .Aggregate([[],[]], function (result, item) { 
     result[0].push(item.Key()); 
     result[1].push(item.Average("$[1]")); 
     return result; 
    }); 
} 

// -------------------------------------------- 

arrayMeanLinq([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]); 
// -> [[3,4,5,2], [11.5,13,13,20]] 

Như nghi ngờ, việc triển khai "ưa thích" chậm hơn so với triển khai gốc: jsperf comparison.

+0

Cảm ơn bạn! - Man JS không bao giờ thẳng về phía trước ... – Chrugel

+0

một số cải tiến: - Tôi nghĩ rằng nếu thử nghiệm: index.hasOwnProperty (i) là vô dụng. - Tôi nghĩ parseInt là vô ích khi my_array có số. - Để kiểm tra nếu xảy ra là 0, sử dụng câu? thay thế. ocurr == 0? 0: tổng hợp/xảy ra. –

+0

Chỉ cần làm rõ: Cảm ơn tất cả! Tôi chỉ đơn giản là chọn câu trả lời này, b/c nó mang lại cho tôi kết quả đúng/mong đợi 'ra khỏi hộp'. Với giải pháp (rất thanh lịch) từ robertklep & Adrian Maire tôi kết thúc với các chuỗi trong 'nhãn' của tôi, nó không phải là vấn đề, nhưng Tomalak đã đưa ra một giải pháp phù hợp. – Chrugel

0
var temp = {}; 
my_array[0].map(function(label, i) { 
    if (! temp[label]) 
    { 
    temp[label] = []; 
    } 
    temp[label].push(my_array[1][i]); 
}); 
var result = [ [], [] ]; 
for (var label in temp) { 
    result[0].push(label); 
    result[1].push(
    temp[label].reduce(function(p, v) { return p + v })/temp[label].length 
); 
} 
0

Chức năng này không sắp xếp mảng kết quả như trong ví dụ kết quả của bạn. Nếu bạn cần phân loại, chỉ cần nói tôi và tôi sẽ thêm nó.

function getMeanArray(my_array) 
{ 
    m = {}; //id={count,value} 
    for(var i = 0; i<my_array[0].length; i++){ 
     if (m[my_array[0][i]]===undefined) 
     { 
      m[my_array[0][i]]={count:0, value:0}; 
     } 
     m[ my_array[0][i] ].value += my_array[1][i]; // accumulate the values in the corresponding place 
     m[ my_array[0][i] ].count++; // count the occurences 
    } 
    var my_mean_array=[[],[]]; 
    for (var id in m) 
    { 
     my_mean_array[0].push(id); 
     my_mean_array[1].push(m[id].count!=0?m[id].value/m[id].count:0); 
    } 
    return my_mean_array; 
} 
Các vấn đề liên quan