Javascript переставить массив по тому же ключу объекта - PullRequest
1 голос
/ 05 апреля 2019

Что у меня есть:

myArray = [ {type: "My Application"}, {type: "My Component"}, {color: ["red"] } ]

Что мне нужно:

withUniqueKeys = [ {type: ["My Application", "My Component"] }, {color: ["red"]} ]

Как бы я перебрал myArray, чтобы получить массив, подобный withUniquKeys? Я слишком долго играл с этим WAAAYYYY. Решение с lodash тоже подойдет.

Ответы [ 5 ]

4 голосов
/ 05 апреля 2019

Вы можете использовать уменьшить и Object.entries

let myArray = [ {type: "My Application"}, {type: "My Component"}, {color: "red" } ]

let op = myArray.reduce((op,inp)=>{
  let [key,value] = Object.entries(inp)[0]
  op[key] = op[key] || []
  op[key].push(value)
  return op
},{})

// in case you want property with one value to be object only

let final = Object.entries(op)
           .map(([key,value]) => ( {[key]: value.length === 1 ? value[0] : value}))

console.log(final)

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

let myArray = [ {type: "My Application"}, {type: "My Component"}, {color: "red" } ]

let op = myArray.reduce((op,inp)=>{
  let [key,value] = Object.entries(inp)[0]
  op[key] = op[key] || []
  op[key].push(value)
  return op
},{})

console.log(op)
1 голос
/ 05 апреля 2019

Вы можете сделать это с помощью Array.prototype.reduce () и Object.entries () , например:

const arr = [{type: "My Application"}, {type: "My Component"}, {color: "red" }];

const result = Object.entries(arr.reduce((acc, x) => {
  Object.entries(x).forEach(([k, v]) => {
    acc[k] = [...(acc[k] || []), v];
  });
  return acc;
}, {})).map(([k, v]) => ({ [k]: v.length > 1 ? v : v[0] }));

console.log(result);
1 голос
/ 05 апреля 2019

Попробуйте это:

  1. Уменьшить начальный массив для группирования записей по ключам
  2. Сопоставить записи объекта с массивом соответствующих объектов

let myArray = [ {type: "My Application"}, {type: "My Component"}, {color: ["red"] } ]

myArray = myArray.reduce((acc, el) => {
  let prop = Object.keys(el)[0];
  if (!acc[prop]) acc[prop] = [el[prop]];
  else acc[prop].push(el[prop])
  return acc;
},{})

myArray = Object.keys(myArray).map(d => ({[d]:myArray[d].length ===1?myArray[d][0]:myArray[d]}));

console.log(myArray)
0 голосов
/ 05 апреля 2019

Другие ответы выглядят хорошо, вот короткая альтернатива, также с использованием Array.reduce и Object.entries:

const myArray = [{type: "My Application"}, {type: "My Component"}, {color: "red"}];

const withUniqueKeys = Object.entries(
  myArray.reduce((result, item) => {
    const [key, val] = Object.entries(item)[0];
    result[key] = result[key] ? [...[result[key]], val] : val;
    return result;
  }, {})
).map(([key, val]) => ({[key]: val}));

console.log(withUniqueKeys);
0 голосов
/ 05 апреля 2019

Во-первых, вы можете использовать Array.reduce () , чтобы выполнить группировку по keys. Затем на втором шаге вы можете использовать Array.map () поверх сгенерированного Object.entries () , чтобы получить желаемую структуру:

let myArray = [
  {type: "My Application", category: "game"},
  {type: "My Component", category: "other"},
  {color: "red" }
];

let res = myArray.reduce((acc, curr) =>
{
    Object.keys(curr).forEach(k =>
    {
        acc[k] = (acc[k] || []).concat(curr[k]);
    });
    return acc;
}, {});

res = Object.entries(res).map(([k, v]) => ({[k]: v.length > 1 ? v : v[0]}));

console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Обратите внимание, этот подход также будет работать, если ваши входные объекты имеют более одной пары key/value.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...