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

'search': function(value) {
    const res1 = Col1.find({ title: new RegExp(value, 'i') }, { fields: { title: 1, type: 1 } }).fetch() || [],
          res2 = Col2.find({ title: new RegExp(value, 'i') }, { fields: { title: 1, type: 1 } }).fetch() || []

    let result = res1.concat(res2)

    return result
}

Предположим, что первая коллекция даст мне «автомобили» для type - поля, а вторая даст мне «животных».

Если заголовок совпадает, мне нужно изменить type - поле и добавить контент.

{ _id: 1, title: 'mercedes', type: 'cars' }
{ _id: 2, title: 'monkey', type: 'animals' }
{ _id: 3, title: 'jaguar', type: 'cars' }
{ _id: 4, title: 'jaguar', type: 'animals' }

Должен быть преобразован в

{ _id: 1, title: 'mercedes', type: 'cars' }
{ _id: 2, title: 'monkey', type: 'animals' }
{ title: 'jaguar', type: 'multiple', results: [
    { _id: 3, title: 'jaguar', type: 'cars' }
    { _id: 4, title: 'jaguar', type: 'animals' }
] }
2
user3142695 28 Май 2017 в 22:14

2 ответа

Лучший ответ

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

var data = [{ _id: 1, title: 'mercedes', type: 'cars' }, { _id: 2, title: 'monkey', type: 'animals' }, { _id: 3, title: 'jaguar', type: 'cars' }, { _id: 4, title: 'jaguar', type: 'animals' }],
    result = data.reduce(function (titles) {
        return function (r, a) {
            if (titles[a.title]) {
                if (titles[a.title].results.length === 1) {
                    r[titles[a.title].index] = { title: a.title, type: 'multiple', results: titles[a.title].results };
                }
                titles[a.title].results.push(a);
            } else {
                titles[a.title] = { index: r.push(a) - 1, results: [a] };
            }
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Вы можете переместить хеш-таблицу за пределы замыкания.

var data = [{ _id: 1, title: 'mercedes', type: 'cars' }, { _id: 2, title: 'monkey', type: 'animals' }, { _id: 3, title: 'jaguar', type: 'cars' }, { _id: 4, title: 'jaguar', type: 'animals' }],
    titles = Object.create(null),
    result = data.reduce(function (r, a) {
        if (titles[a.title]) {
            if (titles[a.title].results.length === 1) {
                r[titles[a.title].index] = { title: a.title, type: 'multiple', results: titles[a.title].results };
            }
            titles[a.title].results.push(a);
        } else {
            titles[a.title] = { index: r.push(a) - 1, results: [a] };
        }
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1
Nina Scholz 28 Май 2017 в 20:25

Вы можете получить количество для каждого заголовка и затем создать новый массив, используя filter для каждого заголовка:

const a = [
  { _id: 1, title: 'mercedes', type: 'cars' },
  { _id: 2, title: 'monkey', type: 'animals' },
  { _id: 3, title: 'jaguar', type: 'cars' },
  { _id: 4, title: 'jaguar', type: 'animals' }
],
  titles = [...new Set(a.map(({title}) => title))] // count for each title
    .map(t => Object.assign({[t]: a.filter(({title}) => title === t).length})) // current title count
    .reduce((acc, v) => Object.assign(acc, v), {}); // form an object for convenience
    
const res = Object.keys(titles) // for each title
  .reduce((acc, t) => (titles[t] === 1) // if not multiple
    ? acc.concat(a.filter(({title}) => title === t)) // add the element
    : acc.concat(Object.assign({title: t, type: 'multiple', // form 'multiple' element
    	results: a.filter(({title}) => title === t)}))
  , [])
  
console.log(res)
0
Egor Stambakio 28 Май 2017 в 19:50