微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何按顺序排列数组对象

如何解决如何按顺序排列数组对象

我是 JavaScript 编程的新手,我有一个场景如下 -

我有一个元素数组列表的输入 --> [abc,xyz,123] 并且输出将在数组对象中如下所示

[
{
"label" : "positive","id" : "abc"
},{
"label" : "positive","id" : "xyz"
},{
"label" : "negative",{
"label" : "positive and negative",{
"label" : "neg","id" : "123"
},"id" : "xyz"
}
]

现在我必须根据输入序列对输出进行排序 -

这里 abc 是第一个元素 xyz 是第二个元素 123是第三个元素

所以我的输出应该是这样的,所有的 id="abc" 应该先是,然后是 "xyz" 对象,然后是 "123" 对象

[
{
"label" : "positive","id" : "123"
}
]

关于我们如何实现这一目标的任何建议,请

解决方法

您可以首先使用 Map(一种类似对象的数据结构,可让您存储键值对)通过 id 对您的对象数组进行分组。键将是 id,而值将是一个以该键作为其 ID 的对象数组。将所有对象分组到 Map 后,您可以在数组 [abc,xyz,123] 上使用 .flatMap()。首先创建 Map(而不是为数组中的每个元素搜索项目)允许您保持线性:

const target = ['abc','xyz','123'];
const arr = [{ "label": "positive","id": "abc" },{ "label": "positive","id": "xyz" },{ "label": "negative",{ "label": "positive and negative",{ "label": "neg","id": "123" },"id": "xyz" } ];

const grouped = arr.reduce((acc,obj) => {
  const seen = acc.get(obj.id) || []; // get the seen array,if it doesn't exist,default it []
  return acc.set(obj.id,seen.concat(obj)); // add the current object to its seen array,and update that Map
},new Map);

const res =  target.flatMap(id => grouped.get(id)); // convert every value in arr to it's corresponding array from the Map held at `id`
console.log(res);

如果您不习惯使用 Maps、reduce 和 flatMap,您可能会发现以下方法更容易理解。它采用与上述相同的逻辑,只是以一种更命令的方式:

const target = ['abc',"id": "xyz" } ];

const grouped = {};
for(const obj of arr) {
  const seen = grouped[obj.id] || [];
  grouped[obj.id] = seen.concat(obj);
}

const res = [];
for(const id of target) {
  res.push(...grouped[id]);
}
console.log(res);

以上通过创建一个名为 grouped 的对象来工作。这个想法是将 id 中每个对象的 arr 值存储为该对象内的键。一个对象不能有重复的键,所以如果我们遇到一个来自 arr 的对象,它的 id 已经是对象中的一个键,我们可以将该对象作为值添加到保存在钥匙。如果来自 id 的对象的 arr 没有出现在 grouped 中,我们可以添加它,并将其值设置为包含当前对象的数组。这个想法是创建一个这种形式的对象:

{ 
  "123": [ { "label": "neg","id": "123" } ],"abc": [ { "label": "positive","id": "abc" } ],"xyz": [ { "label": "positive","id": "xyz" } ] 
}

在构建上面的 grouped 对象时,这一行检查上面分组的对象是否已经包含当前对象 id,如果是,则将 seen 设置为该键保存的数组,否则,它设置为空数组:

const seen = grouped[obj.id] || [];

然后我们更新 seen 数组和 grouped 对象以添加当前对象:

grouped[obj.id] = seen.concat(obj);

既然一切都已分组,我们可以使用此对象来获取与使用 id 的特定 grouped[id] 关联的对象。在这种情况下,我们希望将 id 中的每个 target 转换为其关联的对象。这可以通过使用 target 循环遍历 for...of 数组中的 id,然后使用 grouped 对象获取与该 id 关联的对象来完成。然后,我们可以使用以下命令将我们从 grouped 获得的数组中的所有元素推入 res 数组:

res.push(...grouped[id]);

这会将 grouped[id] 返回的数组中的每个元素推送到 res 数组中。这与使用 res.push(grouped[id]) 不同,因为这会将整个分组数组(不仅仅是元素)推入 res 数组。通过使用 spread syntax (...),我们将分组数组中的元素作为 individual arguments 传递给 .push(),允许我们只推送元素。

,

你可以这样做。

我们首先从我们需要的序列 {abc: 0,xyz: 1,123: 2} 创建一个像 ["abc","xyz","123"] 这样的优先级映射,然后使用这个映射对数组中的项目进行排序

const data = [{ "label": "positive","id": "xyz" } ];
const sequence = ["abc","123"];

const sortData = (list,order) => {
  const priority = {};
  order.forEach((item,index) => (priority[item] = index));
  return list.sort((itemA,itemB) => priority[itemA.id] - priority[itemB.id]);
};

console.log(sortData(data,sequence));

,

您正在寻找自定义排序功能。您的排序函数根据 id 值在原始输入数组中首次出现的位置做出决定。

const input = [
  {label: "positive",id: "abc"},{label: "positive",id: "xyz"},{label: "negative",{label: "positive and negative",{label: "neg",id: "123"},];

const firstIdPos = input.reduce((a,c,i) => {
  a[c.id] = a[c.id] ?? i;
  return a;
},{});

console.log({firstIdPos});

console.log(input.sort((a,b) => firstIdPos[a.id] - firstIdPos[b.id]));

,

好吧,以下可能是我过火了,但这会给你一个 O(n) 时间复杂度。在这里,我们首先构建 LinkedList,因为我们循环遍历您的 input 数组。 LinkedList 帮助我们O(1)插入节点,如果我们通过节点引用插入。我们只是根据 Map 中的 id 继续存储最新的节点引用

最后,我们将该 LinkedList 中的条目转换为 array

我还没有对它进行彻底的测试,但我认为它应该可以工作。

当然,我正在使用空间来构建额外的 LinkedList 和一个 Map(对于其他人共享的数组实现,您无论如何都必须这样做);

const input = [{
    "label": "positive","id": "abc"
  },{
    "label": "positive","id": "xyz"
  },{
    "label": "negative",{
    "label": "positive and negative",{
    "label": "neg","id": "123"
  },]

// Class Begin
class Node {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

class LinkedList {
  constructor(data) {
    this.head = new Node(data);
    this.tail = this.head;
  }

  convertToArr() {
    let temp = this.head;
    const output = [];

    while (temp !== null) {
      output.push(temp.data);
      temp = temp.next;
    }

    return output;
  }

  insertAfterNode(node,newNode) {
    let previousNext = node.next;
    node.next = newNode;
    newNode.next = previousNext;
  }


  insertAtEnd(newNode) {
    this.tail.next = newNode;
    this.tail = newNode;
  }

}
// Class End


// Function to transform input to output.
function transform(input) {
  if (!input.length)
    return [];

  const ll = new LinkedList(input[0]);
  const nodeCache = new Map()
  nodeCache.set(input[0].id,ll.head);

  for (let index = 1; index < input.length; index++) {
    const data = input[index];
    const newNode = new Node(data);

    if (nodeCache.has(data.id))
      ll.insertAfterNode(nodeCache.get(data.id),newNode);
    else
      ll.insertAtEnd(newNode);

    nodeCache.set(data.id,newNode);
  }
  const output = ll.convertToArr();
  return output;
}

const result = transform(input);
console.log(result);

,

这是该问题的通用解决方案。 sortByKey 获取您的 sortKey 数组并返回一个函数,该函数接受您的输入并按它们排序。 sortByKey 还可以选择采用一个函数,该函数从您的输入中提取您想要匹配的键。默认是采用 id 属性,但您可以使用任何您喜欢的内容覆盖它。你可以这样使用它:

const sortByKey = (sortKeys,keyGen = ({id}) => id) => (input) => 
  sortKeys .flatMap (key => input.filter (x => keyGen(x) == key))

const sortKeys = ['abc','123']
const input = [{label: "positive",id: "xyz"}]

console .log (sortByKey (sortKeys) (input))
.as-console-wrapper {max-height: 100% !important; top: 0}

但如果你选择,你也可以命名中间函数,像这样:

const mySort = sortByKey (['abc','123'])
// ... later
mySort (input)

在任何一种情况下,请注意此函数返回一个新数组,按您想要的方式排序。它不会修改原始数组;我们这里不是野蛮人。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。