Как преобразовать данные из дерева объектов в массив объектов, как это - PullRequest
2 голосов
/ 21 октября 2019

Я хочу преобразовать данные из дерева объектов в массив объектов такого типа

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

от:

const input = {
  p1: {
    s1: {
      title: 'scene 1',
      description: 'description 1',
      value: 1,
    },
    s2: {
      title: 'scene 2',
      description: 'description 2',
      value: 32,
    },
    s3: {
      title: 'scene 3',
      description: 'description 3',
      value: 89,
    },
    s4: {
      title: 'scene 3',
      description: 'description 3',
      value: 0,
    },
  },
  p2: {
    s5: {
      title: 'scene 5',
      description: 'description 5',
      value: 0,
    },
    s6: {
      title: 'scene 6',
      description: 'description 6',
      value: 42,
    },
    s7: {
      title: 'scene 7',
      description: 'description 7',
      value: -9,
    },
  },
}

до:

[
  { projectId: 'p1', sceneId: 's1', value: 1, title: 'scene 1' },
  { projectId: 'p1', sceneId: 's2', value: 32, title: 'scene 2' },
  { projectId: 'p1', sceneId: 's3', value: 89, title: 'scene 3' },
  { projectId: 'p2', sceneId: 's6', value: 42, title: 'scene 6' },
]

Я пытался сделать это с Object.entries и Array.reduce с рекурсивной функцией, но я не могу сделать это два дня ...: D

это мои попытки

const recursive = (obj, lvl = 0) => {
  if (typeof obj !== 'object') {

  }
  const value = Object.entries(obj);

  return value.reduce((acc, [key, value]) => {
    if (typeof value !== 'object') {
      return {...acc, [key]: value};
    }
    if (lvl === 0) {

      return {...recursive(value, lvl + 1), sceneId: key };
    }

  }, {})
}



const transform = (data) => {

  const a = Object.entries(data);
  return a.reduce((acc, [key, value]) => {
    return [...acc, recursive(value)];
  }, [])

}

console.log(transform(input))

Пожалуйста, помогите.

Ответы [ 3 ]

3 голосов
/ 21 октября 2019

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

function getFlat(object, keys, values) {
    function iter(object, [key, ...keys], temp = {}) {
        if (key === undefined) {
            if (object.value > 0) {
                result.push(values.reduce((t, k) => ({ ...t, [k]: object[k] }), temp));
            }
            return;
        }
        Object.entries(object).forEach(([k, v]) => iter(v, keys, { ...temp, [key]: k }));
    }

    var result = [];
    iter(object, keys);
    return result;
}

var input = { p1: { s1: { title: 'scene 1', description: 'description 1', value: 1 }, s2: { title: 'scene 2', description: 'description 2', value: 32 }, s3: { title: 'scene 3', description: 'description 3', value: 89 }, s4: { title: 'scene 3', description: 'description 3', value: 0 } }, p2: { s5: { title: 'scene 5', description: 'description 5', value: 0 }, s6: { title: 'scene 6', description: 'description 6', value: 42 }, s7: { title: 'scene 7', description: 'description 7', value: -9 } } },
    output = getFlat(input, ['projectId', 'sceneId'], ['value', 'title']);

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 23 октября 2019

это тоже должно сработать:

const map = (projectId, scenes) => R.reduce(
  (res, [sceneId, scene]) => res.concat(
    R.mergeRight(scene, { sceneId, projectId }),
  ),
  [],
  scenes,
);

const mapScenes = R.useWith(map, [
  R.identity,
  R.toPairs,
]);

const toArray = R.pipe(
  R.toPairs,
  R.map(
    R.apply(mapScenes),
  ),
);

const data = {
  p1: {
    s1: {
      title: 'scene 1',
      description: 'description 1',
      value: 1,
    },
    s2: {
      title: 'scene 2',
      description: 'description 2',
      value: 32,
    },
    s3: {
      title: 'scene 3',
      description: 'description 3',
      value: 89,
    },
    s4: {
      title: 'scene 3',
      description: 'description 3',
      value: 0,
    },
  },
  p2: {
    s5: {
      title: 'scene 5',
      description: 'description 5',
      value: 0,
    },
    s6: {
      title: 'scene 6',
      description: 'description 6',
      value: 42,
    },
    s7: {
      title: 'scene 7',
      description: 'description 7',
      value: -9,
    },
  },
};


console.log('result', toArray(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js" integrity="sha256-xB25ljGZ7K2VXnq087unEnoVhvTosWWtqXB4tAtZmHU=" crossorigin="anonymous"></script>
1 голос
/ 21 октября 2019
   let projects = [];
    for (let project in input) {
        for (let scene in input[project]) {
            projects.push( { projectId: project, sceneId: scene, value: input[project][scene].value, title: input[project][scene].title })
        }
    }

или как то так:

Object.keys(input).flatMap(project => {
        return Object.keys(input[project]).map( scene => {
            return { projectId: project, sceneId: scene, value: input[project][scene].value, title: input[project][scene].title }
        });
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...