javascript 如何通过比较React中同一数组中的Id和reference_id来重新排序数组列表

biswetbf  于 2023-05-21  发布在  Java
关注(0)|答案(3)|浏览(132)

这就是我得到的数组

[
  { id: 1, name: 'hello world', reference_id: null },
  { id: 2, name: 'hello world', reference_id: null },
  { id: 3, name: 'hello world', reference_id: 1 },
  { id: 4, name: 'hello world', reference_id: null },
  { id: 5, name: 'hello world', reference_id: 1 },
  { id: 6, name: 'hello world', reference_id: 2 },
]

我需要把这个数组重新排序成类似这样的东西。

[
  { id: 1, name: 'hello world', reference_id: null },
  { id: 3, name: 'hello world', reference_id: 1 },
  { id: 5, name: 'hello world', reference_id: 1 },
  { id: 2, name: 'hello world', reference_id: null },
  { id: 6, name: 'hello world', reference_id: 2 },
  { id: 4, name: 'hello world', reference_id: null },
]

这是我试过的代码

const parentIndex = skus?.findIndex(item => item.id === item.reference_id);
    console.log(parentIndex)

    if (parentIndex !== -1) {
      const parentId = skus[parentIndex].id;

      const parentItem = skus.splice(parentIndex, 1)[0];
      const referencedItem = skus.find(item => item.id === parentId);

      if (referencedItem) {
        const referencedIndex = skus.indexOf(referencedItem);
        skus.splice(referencedIndex + 1, 0, parentItem);
      } else {
        skus.push(parentItem);
      }
    }

当我运行这段代码时,我得到了一些奇怪的意外结果,大多数时候它不会在第一行之后运行。
有人能帮我解决这个问题吗?我正在努力寻找解决方案。

omjgkv6w

omjgkv6w1#

一个.map()可以帮助定义一个排序标准,这个标准可以被应用,然后稍后再次被删除(通过第二个.map()调用):

const arr=[
  { id: 1, name: 'hello world', reference_id: null },
  { id: 2, name: 'hello world', reference_id: null },
  { id: 3, name: 'hello world', reference_id: 1 },
  { id: 4, name: 'hello world', reference_id: null },
  { id: 5, name: 'hello world', reference_id: 1 },
  { id: 6, name: 'hello world', reference_id: 2 },
];

const res=arr.map(c=>({ref:(c.reference_id??"")+`${c.id}`,el:c}))
             .sort((a,b)=>a.ref.localeCompare(b.ref))
             .map(c=>c.el);

console.log(res)

好的,按照评论中的要求。这里有一个解决方案(只需一个.sort()调用):

const arr=[
  { id: 1, name: 'hello world', reference_id: null },
  { id: 2, name: 'hello world', reference_id: null },
  { id: 3, name: 'hello world', reference_id: 1 },
  { id: 4, name: 'hello world', reference_id: null },
  { id: 5, name: 'hello world', reference_id: 1 },
  { id: 6, name: 'hello world', reference_id: 2 },
];
const crit=o=>(""+(o.reference_id??"")).padStart(4,"0")+"|"+(""+o.id).padStart(4,"0"),
      res=arr.sort((a,b)=>crit(a).localeCompare(crit(b)));

console.log(res);

console.log("these are the computed sort criteria:")
console.log(res.map(crit))

第二个版本可以处理任何数字id的孩子(最大为“9999”)。

arknldoa

arknldoa2#

你可以通过一个自定义的sort()函数来实现:

const list = [
  { id: 1, name: "hello world", reference_id: null },
  { id: 2, name: "hello world", reference_id: null },
  { id: 3, name: "hello world", reference_id: 1 },
  { id: 4, name: "hello world", reference_id: null },
  { id: 5, name: "hello world", reference_id: 1 },
  { id: 6, name: "hello world", reference_id: 2 }
];

list.sort((a, b) => {

  // obj.reference_id = 1 goes before obj.reference_id = 2
  if (a.reference_id && b.reference_id) {
    return a.reference_id - b.reference_id;
  }

  // obj.reference_id = 1 goes before obj.id = 2
  if (a.reference_id && !b.reference_id) {
    return a.reference_id - b.id;
  }

  // again, obj.reference_id = 1 goes before obj.id = 2
  if (!a.reference_id && b.reference_id) {
    return a.id - b.reference_id;
  }

  // if reference_id is null then obj.id = 1 goes before obj.id = 2
  return a.id - b.id;
});

console.log(list);

更新

如果
1-给定的数组可以按id或
2-可能会有嵌套引用,如评论中所述,这是我建议的解决方案:

const list = [
  { id: 7, name: "hello world", reference_id: 3 },
  { id: 3, name: "hello world", reference_id: 1 },
  { id: 4, name: "hello world", reference_id: null },
  { id: 1, name: "hello world", reference_id: null },
  { id: 5, name: "hello world", reference_id: 1 },
  { id: 2, name: "hello world", reference_id: null },
  { id: 6, name: "hello world", reference_id: 2 }
];

list
  .sort((a, b) => a.id - b.id) // first sort by id
  .sort((a, b) => a.reference_id - b.reference_id) // then by referenceId
  .forEach((dep, index) => { // then move dependant entries next to their parents
    if (dep.reference_id !== null) {
    
      // find index of parent
      const parentIndex = list.findIndex((p) => p.id === dep.reference_id);
      
      // find a sibling that is already moved next to the common parent
      const siblingIndex = list.findLastIndex(
        (s, i) => s.reference_id === dep.reference_id && i < index
      );

      // remove entry from its original slot
      list.splice(index, 1);

      // calc its new slot
      const depNewIndex = (parentIndex + 1 > siblingIndex) ? parentIndex + 1 : siblingIndex + 1;

      // move
      list.splice(depNewIndex, 0, dep);
    }
  });

console.log(list);
ni65a41a

ni65a41a3#

看起来你所追求的是,带有reference_id的元素紧跟在带有id的元素之后。
如果是这样的话,那么你实际上是在寻找一个数据的前序遍历作为一个树(参见:tree traversal)。以下方法适用于任何嵌套级别。

const input = [
  { id: 4, reference_id: null },
  { id: 7, reference_id: 6 },
  { id: 5, reference_id: 1 },
  { id: 2, reference_id: null },
  { id: 1, reference_id: null },
  { id: 3, reference_id: 1 },
  { id: 6, reference_id: 2 },
];

// build the tree
const tree = input.reduce((a, node) => {
  (a[node.reference_id] ??= []).push({
    node,
    children: (a[node.id] ??= []),
  });

  return a;
}, {})['null'];

// recursive depth-first traversal
function flatten(arr) {
  let result = [];
  for (const { node, children } of arr.sort((a, b) => a.node.id - b.node.id)) {
    result.push(node, ...flatten(children));
  }

  return result;
}

const sorted = flatten(tree);

console.log(sorted.map((o) => JSON.stringify(o)).join(',\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

但是,如果你只是在寻找一个id的主排序,其中元素共享一个reference_id分组在一起,那么你可以首先group-byreference_id,然后在flattening分组数组之前按每个组的第一个元素的id排序。这里对input数组的副本执行id的初始排序。

const input = [
  { id: 4, reference_id: null },
  { id: 13, reference_id: null },
  { id: 5, reference_id: 1 },
  { id: 2, reference_id: null },
  { id: 1, reference_id: null },
  { id: 3, reference_id: 1 },
  { id: 6, reference_id: 2 },
];

const sorted = Object
  .values(
    [...input]
      .sort((a, b) => a.id - b.id)
      .reduce((a, c, i) => ((a[c.reference_id ?? `null_${i}`] ??= []).push(c), a), {})
  )
  .sort(([a], [b]) => a.id - b.id)
  .flat();

// logging
console.log(sorted.map((o) => JSON.stringify(o)).join(',\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

相关问题