Свести вложенный объект Javascipt - PullRequest
3 голосов
/ 11 марта 2020

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

[{
    a: 1,
    b: 2,
    c: [{
        x: 10,
        y: 20
    }, {
        x: 30,
        y: 40
    }]
}, {
    a: 3,
    b: 4,
    c: [{
        x: 50,
        y: 60
    }, {
        x: 70,
        y: 80
    }]
}]

Исходя из этого, я хочу получить что-то вроде этого:

[{
    a: 1,
    b: 2,
    x: 10,
    y: 20
}, {
    a: 1,
    b: 2,
    x: 30,
    y: 40
}, {
    a: 3,
    b: 4,
    x: 50,
    y: 60
}, {
    a: 3,
    b: 4,
    x: 70,
    y: 80
}]

Конечно, я мог бы просто перебрать объект с двумя циклами for и поместить информацию о результате в отдельный массив, но мне интересно, есть ли более простое решение. Я уже пытался поиграться с flatMap. Это работает, если мне нужна только часть моего вложенного объекта c, но я не знаю, как сопоставить a и b этому объекту.

Как некоторые из вас просили о некоторых рабочий код, это должно сделать это (не проверено):

let result = [];

for (const outer of myObj)
  for (const inner of outer.c)
    result.push({a: outer.a, b: outer.b, x: inner.x, y: inner.y});

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

Ответы [ 5 ]

3 голосов
/ 11 марта 2020

Вы можете использовать flatMap метод вместе с map для свойства 'c':

var input = [{ a: 1, b: 2, c: [{ x: 10, y: 20 }, { x: 30, y: 40 }] }, { a: 3, b: 4, c: [{ x: 50, y: 60 }, { x: 70, y: 80 }] }];

const output = input.flatMap(obj =>
  obj.c.map(arr => ({a: obj.a, b: obj.b, x: arr.x, y: arr.y}))
);

console.log(output);
2 голосов
/ 11 марта 2020

В идеале решение должно было бы что-то сказать, как далеко, чтобы начать классифицировать объект как полный объект, простое решение - просто пройти желаемый уровень. Если вы не хотите проходить уровень, вы можете проверить, и если ни одно из свойств не имеет массивов, вы бы классифицировали это как полную запись, но, конечно, logi c - это то, что вам нужно подтвердить .

Если вы хотите универсальную c версию, которая работает с несколькими уровнями, если вы пройдете уровень и, используя рекурсию, вы можете сделать что-то вроде этого ->

const a=[{a:1,b:2,c:[{x:10,y:20},{x:30,y:40}]},{a:3,b:4,c:[{x:50,y:60},{x:70,y:80}]}];


function flattern(a, lvl) {
  const r = [];
  function flat(a, l, o) {
    for (const aa of a) {
      o = {...o};
      for (const [k, v] of Object.entries(aa)) {
        if (Array.isArray(v) && l < lvl) flat(v, l + 1, o);
        else o[k] = v;
      }
      if (l === lvl) r.push(o);
    }
  }
  flat(a, 1);
  return r;
}

console.log(flattern(a, 2));
//console.log(flattern(a, 1));
1 голос
/ 11 марта 2020

Одно из решений, использующих уменьшение:

const list = [{
    a: 1,
    b: 2,
    c: [{
        x: 10,
        y: 20
    }, {
        x: 30,
        y: 40
    }]
}, {
    a: 3,
    b: 4,
    c: [{
        x: 50,
        y: 60
    }, {
        x: 70,
        y: 80
    }]
}]

const flatten = (arr) => {
  return arr.reduce((flattened, item) => {
    return [
      ...flattened,
      ...item.c.reduce((flattenedItem, i) => {
        return [
          ...flattenedItem,
          {
            a: item.a,
            b: item.b,
            x: i.x,
            y: i.y
          }
        ]
      }, [])
    ]
  }, [])
}

console.log(flatten(list));
1 голос
/ 11 марта 2020
Решение

A flatMap будет выглядеть следующим образом:

const result = myObj.flatMap(outer =>
  outer.c.map(inner =>
    ({a: outer.a, b: outer.b, x: inner.x, y: inner.y})
  )
);

Конечно, если ваш объект имеет несколько слоев, а не только два, и, возможно, даже несколько или неизвестные свойства, которые имеют такую ​​вложенность, вы следует попытаться реализовать рекурсивное решение. Или итеративный, где вы * l oop над массивом имен свойств (для вашего примера ["c"]) и применяете уровень выравнивания по уровню.

0 голосов
/ 11 марта 2020

Использование двух сокращений для выравнивания вашей структуры

const input = [{
  a: 1,
  b: 2,
  c: [{
    x: 10,
    y: 20
  }, {
    x: 30,
    y: 40
  }]
}, {
  a: 3,
  b: 4,
  c: [{
    x: 50,
    y: 60
  }, {
    x: 70,
    y: 80
  }]
}]

const result = input.reduce((acc_0, x) => {
  return [...acc_0, ...x.c.reduce((acc_1, y) => {
    const obj = {
      a: x.a,
      b: x.b,
      x: y.x,
      y: y.y
    }
    acc_1.push(obj);
    return acc_1;
  }, [])]
}, []);

console.log(result)
...