2014-12-30 2 views
-2

У меня есть два массива объектов. У одного из них есть количество посетителей в день, другое - количество документов в день. Пример:Объединить массивы объектов по уникальному ключу

var visitors = [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ]; 
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95 } ]; 

Даты могут быть разными в каждом массиве. Как я могу преобразовать массивы следующую структуру (что означает объединить их по дате ключа):

[ { date: '2014.12.15', visits: 0, docs: 31 }, // here visits = 0 because there were no visitors at this date 
    { date: '2014.12.25', visits: 441, docs: 0 }, // here docs = 0 because no docs were created at this date 
    { date: '2014.12.26', visits: 630, docs: 60 }, 
    { date: '2014.12.30', visits: 71, docs: 95 },  
] 

Инструменты допустима: JavaScript и Undescore.js.

Спасибо

+0

конечно, я пробовал много вещей, мой код теперь более 2-х страниц, чтобы решить эту проблему, но я сомневаюсь, что я буду право путь. Я считаю, что это может быть понятное сообщество. – kaytrance

+0

Да, это должно быть всего несколько (менее 10) строк кода ... – Cerbrus

+0

Не пытайтесь оскорбить, но если вы решили создать две страницы кода для решения проблемы, то [принцип KISS] (http://en.wikipedia.org/wiki/KISS_principle) был полностью проигнорирован. – Sukima

ответ

1

Давайте поговорим об этом в родной JS.

Во-первых, давайте превратить эти 2 массивы в более чувственных объектов:

function reduceDates(prev, curr){ 
    var date = Object.keys(curr)[0]; // This is why {date : value} makes no sense. 
    prev[date] = curr[date]; 
    return prev; 
} 

var v = visitors.reduce(reduceDates, {}); // {2014.12.25: 141, 2014.12.26: 630, 2014.12.30: 71} 
var d = documents.reduce(reduceDates, {}); // {2014.12.15: 31, 2014.12.26: 60, 2014.12.30: 95} 

Давайте объединить эти 2 в один объект:

var combined = {}; 
for(var key in v){ 
    combined[key] = { date: key, visits: v[key], docs: 0 }; 
} 
for(var key in d){ 
    combined[key] = combined[key] || { date: key, visits: 0 }; 
    combined[key].docs = d[key]; 
} 

Теперь combined это очень хороший объект, содержащий ваши данные:

{ 
    "2014.12.25": { date: "2014.12.25", visits: 141, docs: 0 }, 
    "2014.12.26": { date: "2014.12.26", visits: 630, docs: 60 }, 
    "2014.12.30": { date: "2014.12.30", visits: 71, docs: 95 }, 
    "2014.12.15": { date: "2014.12.15", visits: 0, docs: 31 } 
} 

Однако, поскольку вам нужен массив объектов, мы придется повторять еще один раз:

var result = []; 
for(var key in combined){ 
    result.push(combined[key]); 
} 

Результат:

[ 
    { date: "2014.12.25", visits: 141, docs: 0 }, 
    { date: "2014.12.26", visits: 630, docs: 60 }, 
    { date: "2014.12.30", visits: 71, docs: 95 }, 
    { date: "2014.12.15", visits: 0, docs: 31 } 
] 

Конечно, это не самый короткий, или лучший способ, чтобы получить желаемый результат, но я надеюсь, что это дает вам идея шагов, участвующих в этом процессе.

+0

отличный ответ! – kaytrance

+0

Downvoter: обратите внимание? Если бы я допустил ошибку, я бы хотел узнать из нее. – Cerbrus

0

Все, что вам нужно сделать, это цикл по вашим данным.

var visitors = [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ]; 
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95 } ]; 
var data = {}; 
visitors.forEach(function(el){var k = Object.keys(el)[0]; data[k] = data[k] || {}; data[k].visits = el[k];}); 
documents.forEach(function(el){var k = Object.keys(el)[0]; data[k] = data[k] || {}; data[k].docs = el[k];}); 
for(prop in data){ 
    if(data[prop].docs === void 0){data[prop].docs = 0}; 
    if(data[prop].visits === void 0){data[prop].visits = 0}; 
} 

Это дает ваши данные в комбинированном манере, все, что вам нужно сделать, это добавить логику, чтобы перенести дату с ключа на объект.

+0

'void 0'? В самом деле? – Cerbrus

+0

@Cerbrus 'void 0' является полностью допустимым использованием, я не понимаю, какова ваша точка. – Nit

+0

Несомненно, это действительно так, но это параноидальное использование чего-то, что люди, совершенно новые для JS, возможно, не знакомы. – Cerbrus

0

Другим способом с помощью подчеркивания, чтобы объединить массивы:

var visitors = [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ]; 
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95 } ]; 

var visits = new Array(); 
var docs = new Array(); 

for (i=0; i < visitors.length; i++) { 
    for (key in visitors[i]) {  
     visits.push({"date": key, "visits": visitors[i][key], "docs":0}); 
    } 
} 

for (i=0; i < documents.length; i++) { 
    for (key in documents[i]) { 
     docs.push({"date": key,"docs": documents[i][key]}); 
    } 
} 

mergeByProperty(visits, docs, 'date'); 

function mergeByProperty(visits, docs, prop) { 
    _.each(docs, function(arr2obj) { 
     var arr1obj = _.find(visits, function(arr1obj) { 
      return arr1obj[prop] === arr2obj[prop]; 
     }); 

     //If the object already exist extend it with the new values from arr2, otherwise just add the new object to arr1 
     arr1obj ? _.extend(arr1obj, arr2obj) : visits.push(arr2obj); 
    }); 
} 

console.log(visits); 
Смежные вопросы