【问题标题】:How to order an array by keeping certain elements always on top如何通过使某些元素始终位于顶部来对数组进行排序
【发布时间】:2020-09-03 05:58:15
【问题描述】:

我有一个数组,我想将某些项目始终放在最上面。我从 API 收到如下响应。

const itemInventorylocationTypes = [
    {
        itemInventorylocationId: '00d3898b-c6f8-43eb-9470-70a11cecbbd7',
        itemInventorylocationCd: 'Rummsan'
    },
    {
        itemInventorylocationId: '1e8cd068-3cfc-4e25-af22-4a8fec3c794d',
        itemInventorylocationCd: 'Yes'
    },
    {
        itemInventorylocationId: 'f78fb228-7d1a-4cad-bde7-956e5f46db69',
        itemInventorylocationCd: 'Rambo'
    },
    {
        itemInventorylocationId: 'ce4a8a4d-a282-424b-bb2a-5a5187db02e0',
        itemInventorylocationCd: 'Veronica'
    },
    {
       itemInventorylocationId: '87082949-b148-4766-ad1d-148b91a46a79',
        itemInventorylocationCd: 'Hunnumous'
    },
    {
        itemInventorylocationId: '0fdaf8eb-07f4-4300-9c20-44f788724c59',
        itemInventorylocationCd: 'PerryPerry'
    },
    {
        itemInventorylocationId: '4f75ed92-68c0-4137-be37-d64ae77653c7',
        itemInventorylocationCd: 'Dont know why'
    },
    {
        itemInventorylocationId: '50efa718-6eed-4eff-ad13-305864c1b243',
        itemInventorylocationCd: 'Its ok'
    },
    {
        itemInventorylocationId: 'c7d3275b-cad9-45b2-9065-0fefdf7fc241',
        itemInventorylocationCd: 'This is some random thing'
    }
];

现在我希望Veronica,rambo, Hunnumous,PerryPerry and Rummsan 的元素按此顺序首先出现。

为此,我创建了一个参考数组,然后使用 lodash intersectionWith 和 DifferenceWith 将它们分解。

const referenceArray = ['Veronica', 'Rambo', 'Hunnumous', 'PerryPerry', 'Rummsan'];
 
export const sortitemInventory = (itemInventorylocationTypes: DropdownOption[]) => {
    const commonElements = _.intersectionWith(itemInventorylocationTypes, referenceArray, (x, y) => x.itemInventorylocationCd == y);
    const differentElements = _.differenceWith(itemInventorylocationTypes, referenceArray, (x, y) => x.itemInventorylocationCd == y);
    console.log(commonElements);
    console.log(differentElements);
    cosnst newArray = [...commonElements, ...differentElements];
};
 

预期公共元素按referenceArray 中的顺序排列。但我得到的是,

const itemInventorylocationTypes = [
    {
        itemInventorylocationId: '00d3898b-c6f8-43eb-9470-70a11cecbbd7',
        itemInventorylocationCd: 'Rummsan'
    },
    {
        itemInventorylocationId: 'f78fb228-7d1a-4cad-bde7-956e5f46db69',
        itemInventorylocationCd: 'Rambo'
    },
    {
        itemInventorylocationId: 'ce4a8a4d-a282-424b-bb2a-5a5187db02e0',
        itemInventorylocationCd: 'Veronica'
    },
    {
        itemInventorylocationId: '87082949-b148-4766-ad1d-148b91a46a79',
        itemInventorylocationCd: 'Hunnumous'
    },
   {
        itemInventorylocationId: '0fdaf8eb-07f4-4300-9c20-44f788724c59',
        itemInventorylocationCd: 'PerryPerry'
    }
];

还有其他方法吗?我可能可以循环每个元素,然后将其推送到新数组,但只是检查是否有更好的方法。

【问题讨论】:

  • intersectionWith 将数组的顺序保存在第一个参数中。这就是为什么您需要重新订购您的 commonElements
  • 好吧,您可以在将其用作参考之前将reverse() referenceArray 用作参考。
  • @HaoWu,反转referenceArray将只得到带有字符串的数组,而不是带有对象的数组。

标签: javascript reactjs typescript lodash


【解决方案1】:

你可以这样做:

const itemInventorylocationTypes=[{Id:"00d3898b-c6f8-43eb-9470-70a11cecbbd7",Cd:"Rummsan"},{Id:"1e8cd068-3cfc-4e25-af22-4a8fec3c794d",Cd:"Yes"},{Id:"f78fb228-7d1a-4cad-bde7-956e5f46db69",Cd:"Rambo"},{Id:"ce4a8a4d-a282-424b-bb2a-5a5187db02e0",Cd:"Veronica"},{Id:"87082949-b148-4766-ad1d-148b91a46a79",Cd:"Hunnumous"},{Id:"0fdaf8eb-07f4-4300-9c20-44f788724c59",Cd:"PerryPerry"},{Id:"4f75ed92-68c0-4137-be37-d64ae77653c7",Cd:"Dont know why"},{Id:"50efa718-6eed-4eff-ad13-305864c1b243",Cd:"Its ok"},{Id:"c7d3275b-cad9-45b2-9065-0fefdf7fc241",Cd:"This is some random thing"}],
      referenceArray = ['Veronica', 'Rambo', 'Hunnumous', 'PerryPerry', 'Rummsan'],
      priority = Object.fromEntries( referenceArray.map((k,i) => [k,i]) )

console.log(priority)

itemInventorylocationTypes.sort((a,b) => 
  priority.hasOwnProperty(b.Cd) - priority.hasOwnProperty(a.Cd)
  || priority[a.Cd] - priority[b.Cd]
)

console.log(itemInventorylocationTypes)

创建一个priority 对象,将每个referenceArray 项目映射到它的索引。

首先 sort 数组基于每个 Cd 是否存在于 priority 中。

(我已经从键名中删除了itemInventorylocation 前缀,使其更具可读性)

priority.hasOwnProperty(b.Cd) - priority.hasOwnProperty(a.Cd)

之所以有效,是因为布尔值在被减去时会被强制转换为数字。

true - true === 0
true - false === 1
false - true === -1
  • 如果a.Cd 出现在优先级中而b.Cd 没有出现,则减法返回-1 并且a 在排序后的数组中优先于b
  • 如果它们都存在优先级,则减法返回0,这是一个falsy 值。然后,检查|| 的第二部分。

如果减法返回0,则根据priority 对象中的Cd 值对项目进行排序

您也可以将Map 用作priority

const itemInventorylocationTypes=[{Id:"00d3898b-c6f8-43eb-9470-70a11cecbbd7",Cd:"Rummsan"},{Id:"1e8cd068-3cfc-4e25-af22-4a8fec3c794d",Cd:"Yes"},{Id:"f78fb228-7d1a-4cad-bde7-956e5f46db69",Cd:"Rambo"},{Id:"ce4a8a4d-a282-424b-bb2a-5a5187db02e0",Cd:"Veronica"},{Id:"87082949-b148-4766-ad1d-148b91a46a79",Cd:"Hunnumous"},{Id:"0fdaf8eb-07f4-4300-9c20-44f788724c59",Cd:"PerryPerry"},{Id:"4f75ed92-68c0-4137-be37-d64ae77653c7",Cd:"Dont know why"},{Id:"50efa718-6eed-4eff-ad13-305864c1b243",Cd:"Its ok"},{Id:"c7d3275b-cad9-45b2-9065-0fefdf7fc241",Cd:"This is some random thing"}],
      referenceArray = ['Veronica', 'Rambo', 'Hunnumous', 'PerryPerry', 'Rummsan'],
      priority = new Map(referenceArray.map((k,i) => [k,i]))

itemInventorylocationTypes.sort((a,b) => 
  priority.has(b.Cd) - priority.has(a.Cd)
  || priority.get(a.Cd) - priority.get(b.Cd)
)

console.log(itemInventorylocationTypes)

【讨论】:

    猜你喜欢
    • 2014-01-27
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多