首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何基于字符串索引对对象数组进行分组和排序

如何基于字符串索引对对象数组进行分组和排序
EN

Stack Overflow用户
提问于 2022-03-10 09:11:21
回答 1查看 69关注 0票数 0

我想将我的平面数组分组&重新排列成一个对象数组,其中每个对象都包含其子属性中的直接后代。

我的输入数据-:

代码语言:javascript
复制
const data = [
  { lineNo: '1' },
  { lineNo: '1-1' },
  { lineNo: '1-2' },
  { lineNo: '1-3' },
  { lineNo: '1-4' },
  { lineNo: '1-11' },
  { lineNo: '1-2-1' },
  { lineNo: '1-2-3' },
  { lineNo: '1-2-2' },
  { lineNo: '1-2-4' },
  { lineNo: '1-3-1' },
  { lineNo: '1-3-2' },
  { lineNo: '1-3-3' },
  { lineNo: '1-11-1' },
  { lineNo: '1-11-2' },
  { lineNo: '1-11-3' },
  { lineNo: '2' },
  { lineNo: '2-1' },
  { lineNo: '2-2' },
  { lineNo: '2-3' },
  { lineNo: '2-2-1' },
  { lineNo: '2-2-2' },
];

我想要的输出-:

代码语言:javascript
复制
const newData = [
  {
    lineNo: '1',
    children: [{ lineNo: '1-1' }, { lineNo: '1-2' }, { lineNo: '1-3' }, { lineNo: '1-4' }, { lineNo: '1-11' }],
  },
  {
    lineNo: '1-2',
    children: [{ lineNo: '1-2-1' }, { lineNo: '1-2-2' }, { lineNo: '1-2-3' }, { lineNo: '1-2-4' }],
  },
  {
    lineNo: '1-3',
    children: [{ lineNo: '1-3-1' }, { lineNo: '1-3-2' }, { lineNo: '1-3-3' }],
  },
  {
    lineNo: '1-11',
    children: [{ lineNo: '1-11-1' }, { lineNo: '1-11-2' }, { lineNo: '1-11-3' }],
  },
  {
    lineNo: '2',
    children: [{ lineNo: '2-1' }, { lineNo: '2-2' }, { lineNo: '2-3' }],
  },
  {
    lineNo: '2-2',
    children: [{ lineNo: '2-2-1' }, { lineNo: '2-2-2' }],
  },
];

注意:生成的数据必须遵循输出中提到的数字顺序。

到目前为止,我所做的-:

代码语言:javascript
复制
const data = [
  { lineNo: '1' },
  { lineNo: '1-1' },
  { lineNo: '1-2' },
  { lineNo: '1-3' },
  { lineNo: '1-4' },
  { lineNo: '1-11' },
  { lineNo: '1-11-1' },
  { lineNo: '1-11-2' },
  { lineNo: '1-11-3' },
  { lineNo: '1-2-1' },
  { lineNo: '1-2-3' },
  { lineNo: '1-2-2' },
  { lineNo: '1-2-4' },
  { lineNo: '1-2-1-1' },
  { lineNo: '1-2-1-2' },
  { lineNo: '1-2-1-3' },
  { lineNo: '1-3-1' },
  { lineNo: '1-3-2' },
  { lineNo: '1-3-3' },
];

function createTree(data: any) {
  const tree: any[] = [];
  data.reduce(
    (r: any, o: any) => {
      o.lineNo
        .split('-')
        .map((_: any, i: any, a: any) => a.slice(0, i + 1).join('-'))
        .reduce((q: any, lineNo: any, i: any, { length }: any) => {
          let temp = (q.children = q.children || []).find((p: any) => p.lineNo === lineNo);
          if (!temp) {
            q.children.push((temp = { lineNo }));
          }
          if (i + 1 === length) {
            Object.assign(temp, o);
          }
          return temp;
        }, r);
      return r;
    },
    { children: tree }
  );

  return tree;
}

const createFlat = (data: any) => {
  const flat: any[] = [];
  const flatData = (data: any) => {
    data.forEach((item: any) => {
      if (item.children) {
        flat.push(item);
        flatData(item.children);
      }
    });
  };
  flatData(data);
  return JSON.parse(JSON.stringify(flat));
};

const getCleanData = (data: any) => {
  const cleanData: any[] = [];
  function delChildren(obj: any) {
    if (obj.children) {
      obj.children.forEach((item: any) => {
        if (item.children) {
          delete item.children;
        }
      });
    }
    return obj;
  }

  data.forEach(function (item: any) {
    cleanData.push(delChildren(item));
  });

  return cleanData;
};

const treeData = createTree(data);
const flatData = createFlat(treeData);
const cleanData = getCleanData(flatData);
console.log(JSON.stringify(cleanData, null, 2));

我正在寻找一个简单和干净的方法。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-10 13:13:58

您可以首先使用“自然”排序对数据进行排序。JavaScript localeCompare有一个选项。

然后创建一个由Map键指定的lineNo,并将具有相同lineNo属性和空children数组属性的对象作为相应的值创建。

然后再次迭代数据,以填充这些children数组。

提取Map值并删除具有空children数组的对象,除非它们是顶级节点(边界情况)。

以下是一个实现:

代码语言:javascript
复制
function createTree(data) {
    // Apply natural ordering
    data = [...data].sort((a, b) => 
        a.lineNo.localeCompare(b.lineNo, "en", { numeric: true })
    );
    // Create key/value pairs for all lineNo in a Map
    let map = new Map(data.map(({lineNo}) => [lineNo, { lineNo, children: [] }]));
    // Populate the children arrays
    for (let {lineNo} of data) {
        map.get(lineNo.replace(/-?\d+$/, ""))?.children?.push({lineNo});
    }
    // Exclude the nodes that have no children, except if they are top-level
    return [...map.values()].filter(({lineNo, children}) => 
        !lineNo.includes("-") || children.length
    );
}

// Demo
const data = [{ lineNo: '1-1' },{ lineNo: '1-2' },{ lineNo: '1-3-2' },{ lineNo: '1-11-2' },{ lineNo: '1-3' },{ lineNo: '1-11' },{ lineNo: '1-2-3' },{ lineNo: '1-2-2' },{ lineNo: '1' },{ lineNo: '1-2-1' },{ lineNo: '1-2-4' },{ lineNo: '1-11-1' },{ lineNo: '1-3-1' },{ lineNo: '1-4' },{ lineNo: '1-3-3' },{ lineNo: '2-1' },{ lineNo: '2-2' },{ lineNo: '2-2-1' },{ lineNo: '1-11-3' },{ lineNo: '2' },{ lineNo: '2-3' },{ lineNo: '2-2-2' },];

console.log(createTree(data));

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71421524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档