【问题标题】:Reorder elements in array of objects重新排序对象数组中的元素
【发布时间】:2019-03-08 10:41:40
【问题描述】:

我有一个对象数组:

const array = [
  {
    id: "5a2524432b68c725c06ac987",
    customOrder: 1,
    name: "One",
  },
  {
    id: "5a2524432b68sgs25c06ac987",
    customOrder: 2,
    name: "Two",
  },
  {
    id: "5a252wfew32b68c725c06ac987",
    customOrder: 3,
    name: "Three",
  },
  {
    id: "5a25gffe32b68c725c06ac987",
    customOrder: 4,
    name: "Four",
  },
  {
    id: "5a2524432b68c725c06acfee7",
    customOrder: 5,
    name: "Five",
  },
  {
    id: "5a2524432b68c725c06ac556",
    customOrder: 6,
    name: "Six",
  },
]

当我更新其中一个对象的 customOrder 并根据 customOrder 更新其他对象时,如果我将索引 2 更改为自定义顺序为 4,我需要编辑另一个对象的 customOrder元素,因此结果将是:

const array = [
  {
    id: "5a2524432b68c725c06ac987",
    customOrder: 1,
    name: "One",
  },
  {
    id: "5a2524432b68sgs25c06ac987",
    customOrder: 2,
    name: "Two",
  },
  {
    id: "5a25gffe32b68c725c06ac987",
    customOrder: 3,
    name: "Four",
  },
  {
    id: "5a252wfew32b68c725c06ac987",
    customOrder: 4,
    name: "Three",
  }
  {
    id: "5a2524432b68c725c06acfee7",
    customOrder: 5,
    name: "Five",
  },
  {
    id: "5a2524432b68c725c06ac556",
    customOrder: 6,
    name: "Six",
  },
]

我正在考虑使用 array.slice() 甚至使用 lodash _.putAt(),但我正在尝试一种实现最佳结果的简单方法

【问题讨论】:

  • 我认为您必须使用一些排序功能。比如归并排序(只是一个例子)并应用基于customOrder键的排序。
  • 您已经在数组索引中有顺序,所以customOrder 是多余的。如果你想移动一些东西,就移动它;那么如果你仍然需要customOrder,用array.forEach((x. i) => x.customOrder = i + 1)重新标记它。
  • 您的问题有 2 个问题陈述:1. 更新相关对象。因此,当您将索引2 处的对象更新为4 时,您还必须回溯其他对象并对其进行更改。 2. 为了保持顺序,您必须对列表进行排序。
  • 如果你改变了不相关的对象的顺序怎么办?

标签: javascript ecmascript-6


【解决方案1】:

您可以分四步完成:

  1. 使用Array.findIndex() 查找与您要在给定索引处更新的值具有相同值的条目。

  2. 然后将此条目的值更改为给定索引处的项目的值。

  3. 然后用新值更新给定索引处的项目。

  4. 最后,交换物品。如果没有具有新值的项目,则对数组进行排序以确保项目被放置在正确的位置。

这个版本改变了数组:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

const swap = (arr, x, y) => [arr[x], arr[y]] = [arr[y], arr[x]];

function setOrder(arr, idx, value) {
  const idx2 = arr.findIndex(x => x.customOrder === value);
  if (idx2 >= 0) arr[idx2].customOrder = arr[idx].customOrder;
  arr[idx].customOrder = value;
  
  if (idx2 >= 0) swap(arr, idx, idx2);
  else arr.sort((a, b) => a.customOrder - b.customOrder);
  return arr;
}

setOrder(array, 2, 4);
console.log(array);

setOrder(array, 2, 10);
console.log(array);

此版本不会改变数组:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

const swap = (arr, x, y) => [arr[x], arr[y]] = [arr[y], arr[x]];

function setOrder(arr, idx, value) {
  const out = [...arr];
  const idx2 = out.findIndex(x => x.customOrder === value);
  if (idx2 >= 0) out[idx2] = { ...out[idx2], customOrder: out[idx].customOrder };
  out[idx] = { ...out[idx], customOrder: value };
  
  if (idx2 >= 0) swap(out, idx, idx2);
  else out.sort((a, b) => a.customOrder - b.customOrder);
  return out;
}

console.log(setOrder(array, 2, 4));
console.log(setOrder(array, 2, 10));

【讨论】:

  • 只是一个小指针。您已经拥有要为其切换值的两个对象的位置/索引。切换对象而不是切换customerOrder然后排序会不会没有意义?
  • @Rajesh,你是完全正确的,那会更理想,我会更新我的答案
【解决方案2】:

您可以使用 splice 删除索引处的项目并将其移动到指定的新索引。然后使用forEach更新customOrder

(如果您不想改变原始数组,您可以使用扩展语法获取数组的副本并使用map

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

function updateOrder(input, index, newIndex) {
  let copy = [...input];
  const removed = copy.splice(index, 1);
  copy.splice(newIndex, 0, removed[0]);
  return copy.map((a, i) => ({ ...a, customOrder: i+1 }))
}

console.log(updateOrder(array, 2, 3))

有突变:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

function updateOrderMutation(input, index, newIndex) {
  const removed = input.splice(index, 1);
  input.splice(newIndex, 0, removed[0]);
  input.forEach((a, i) => a.customOrder = i + 1)
  return input;
}

console.log(updateOrderMutation(array, 2, 3))

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多