簡體   English   中英

使用 lodash 或 vanilla js 重新排序包含父/子關系的對象數組

[英]Reorder array of objects that contain parent/child relationships with lodash or vanilla js

我有一系列對象,例如:

[
    {
        id: 8,
        name: 'Shirts',
        slug: 'shirts',
        parent_id: null
    },
    {
        id: 9,
        name: 'Pants',
        slug: 'pants',
        parent_id: null
    },
    {
        id: 10,
        name: 'Vintage Prints',
        slug: 'vintage-prints',
        parent_id: 8
    },
    {
        id: 11,
        name: 'Cotton Tee',
        slug: 'cotton-tee',
        parent_id: 8
    },
    {
        id: 12,
        name: 'Business Khakis',
        slug: 'business-khakis',
        parent_id: 9
    }
]

我需要的是:

[
    {
        id: 9,
        name: 'Pants',
        slug: 'pants',
        parent_id: null
    },
    {
        id: 12,
        name: 'Business Khakis',
        slug: 'business-khakis',
        parent_id: 9
    },
    {
        id: 8,
        name: 'Shirts',
        slug: 'shirts',
        parent_id: null
    },
    {
        id: 11,
        name: 'Cotton Tee',
        slug: 'cotton-tee',
        parent_id: 8
    },
    {
        id: 10,
        name: 'Vintage Prints',
        slug: 'vintage-prints',
        parent_id: 8
    }
]

我試過什么:這看起來應該有效:

_.orderBy(categories, ['parent_id', 'name'], ['asc', 'asc']);

但我想知道 parent_id 中的空值是否在搞亂它。

編輯:內部和外部結果也應按字母順序排序。 因此,外層的褲子在襯衫之前,棉質 T 恤在兒童層的 Vintage Prints 之前。 請記住,這可以是無限深的層,其中 Cotton Tee 可能是父級等等。

如果每個排序的 object 都可以接收一個索引或級別,以便您知道它嵌套了多少級別,那就太好了。

單一排序不起作用,因為父子關系在對數據進行排序時未考慮。

該解決方案分為三個部分:

  1. 按字母表對數據進行排序,因為以下樹是按插入順序構建的。

  2. 構建具有給定關系的樹。

  3. 遍歷樹並返回排序后的平面數據。

 var data = [{ id: 8, name: 'Shirts', slug: 'shirts', parent_id: null }, { id: 9, name: 'Pants', slug: 'pants', parent_id: null }, { id: 10, name: 'Vintage Prints', slug: 'vintage-prints', parent_id: 8 }, { id: 11, name: 'Cotton Tee', slug: 'cotton-tee', parent_id: 8 }, { id: 12, name: 'Business Khakis', slug: 'business-khakis', parent_id: 9 }].sort(function (a, b) { return a.name.localeCompare(b.name); }), tree = function (data, root) { var r = [], o = {}; data.forEach(function (a) { o[a.id] = { data: a, children: o[a.id] && o[a.id].children }; if (a.parent_id === root) { r.push(o[a.id]); } else { o[a.parent_id] = o[a.parent_id] || {}; o[a.parent_id].children = o[a.parent_id].children || []; o[a.parent_id].children.push(o[a.id]); } }); return r; }(data, null), sorted = tree.reduce(function traverse(r, a) { return r.concat(a.data, (a.children || []).reduce(traverse, [])); }, []) console.log(sorted); console.log(tree);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

帶級別的擴展版本:

 var data = [{ id: 8, name: 'Shirts', slug: 'shirts', parent_id: null }, { id: 9, name: 'Pants', slug: 'pants', parent_id: null }, { id: 10, name: 'Vintage Prints', slug: 'vintage-prints', parent_id: 8 }, { id: 11, name: 'Cotton Tee', slug: 'cotton-tee', parent_id: 8 }, { id: 12, name: 'Business Khakis', slug: 'business-khakis', parent_id: 9 }].sort(function (a, b) { return a.name.localeCompare(b.name); }), tree = function (data, root) { var r = [], o = {}; data.forEach(function (a) { o[a.id] = { data: a, children: o[a.id] && o[a.id].children }; if (a.parent_id === root) { r.push(o[a.id]); } else { o[a.parent_id] = o[a.parent_id] || {}; o[a.parent_id].children = o[a.parent_id].children || []; o[a.parent_id].children.push(o[a.id]); } }); return r; }(data, null), sorted = tree.reduce(function traverse(level) { return function (r, a) { a.data.level = level return r.concat(a.data, (a.children || []).reduce(traverse(level + 1), [])); }; }(0), []); console.log(sorted);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

這是我的解決方案

它處理多個嵌套元素。

我得到了一個解決方案,我使用 lodash 來實現數組相等性,但你也可以在純 JS 中實現它

const sortByLevel = (
  array: ({ id: string, parent_id: string, level: number })[],
  i: number = 0,
): ({ id: string, parent_id: string, level: number })[] => {
  const sortedArray = array
    .map((c) => ({ ...c, level: array.findIndex((a) => a.id === c.parent_id) }))
    .sort((a, b) => a.level - b.level);

  if (
    _.isEqual(
      sortedArray.map((c) => c.id),
      array.map((c) => c.id),
    )
  )
    return sortedArray;

  return sortByLevel(sortedArray, i + 1);
};

const sortByParent = (array: { id: string, parent_id: string }[]): { id: string, parent_id: string }[] => {
  return sortByLevel(
    array
      .map((c) => ({ ...c, level: array.findIndex((a) => a.id === c.parent_id) }))
      .sort((a, b) => a.level - b.level),
    1,
  ).map((c) => {
    const { level, ...card } = c;
    return card;
  });
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM