【JS】数组对象自定义排序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【JS】数组对象自定义排序相关的知识,希望对你有一定的参考价值。

参考技术A replace 的语法

ECMAScript v3 规定, replace() 方法的参数 replacement 可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。
数组的自定义排序,一种是 replace ,一种是较常见易懂的 indexOf 。

数组对象排序

Swift如何使用属性按给定顺序对自定义对象数组进行排序

【中文标题】Swift如何使用属性按给定顺序对自定义对象数组进行排序【英文标题】:Swift how to sort an array of custom objects in a given order with property 【发布时间】:2017-07-30 17:51:47 【问题描述】:

我有一组按特定顺序排列的餐馆 ID。我进行网络调用以获取这些 id 中的每一个的餐厅。我按所有餐厅返回的顺序返回。餐厅是一个自定义类,其中一个属性是 restaurantId。我想按 ID 的顺序对返回的餐厅进行排序。我该怎么做?我想我应该使用排序功能。我将如何继续这样做?可能有重复的餐馆,所以我不能用字典来做。如果 is 是返回的重复餐厅,那么该餐厅的哪个实例首先出现并不重要。

var restaurantIds = [947575, 858914, 255964]
var returnedRestaurant:[Restaurant]!
returnedRestaurant.sorted  (rest1, rest2) -> Bool in
        //How would I go about matching rest1 and rest2 to the list of restaurantIds above?
        rest1.productID......
    

【问题讨论】:

那将按数字排序,我想按 restaurantIds 数组中的自定义顺序对其进行排序。 您正在拨打“网络电话”,但如何?您是一个一个地请求它们,您是一次请求它们并返回一个列表,它们是否以 id 作为数据的一部分返回?我们真的需要更多信息,或者我们只是在猜测解决方案。 【参考方案1】:

如果我理解正确,您希望按照 ID 在 restaurantIds 中出现的顺序对数组进行排序。

Array 提供了index(of:) 方法,它给定一个元素返回它在数组中第一次出现的索引。例如restaurantIds.index(of:858914) 将返回1

您可以使用index(of:) 的结果作为排序键。 IE。在您的排序函数中,您需要比较 rest1 的值将是 restaurantIds.index(of: rest1.productID)

HTH

附录

@vacawama raises 和 issue with 原则上都是正确的,但在实践中可能是错误的...使用restaurantIds.index(of: rest1.productID) a lot 对性能和较长的餐厅 ID 列表不利,您可能需要通过避免重复的index(of:) 调用来优化。然而,对于简短列表,任何性能变化(可能是输赢)都可能微不足道,优化只会使代码复杂化。

TL;DR:YMMV,KISS,提防过早的优化,你的电话。

【讨论】:

我认为这就是 OP 正在寻找的。其余的答案将不起作用。 对于任何正在阅读本文的人来说,@adev 当时是正确的。现在 vacawama 的解决方案也有效,并且是对同一想法的不同看法。任君挑选。 假设 id 是唯一的,可能放入有序集合可能有助于解决索引问题。【参考方案2】:

创建一个字典,将 restaurantID 映射到该 ID 的顺序。然后,您可以使用它对数组进行排序:

var restaurantIds = [947575, 858914, 255964]

// Create a dictionary that maps the order of the restaurantID
var order = [Int: Int]()
for (idx, rid) in restaurantIds.enumerated() 
    order[rid] = idx


var returnedRestaurant:[Restaurant]!

returnedRestaurant.sort  (rest1, rest2) -> Bool in

    // look up the order for the restaurant id.  If the id is missing, use
    // Int.max to put that restaurant at the end of the array

    let order1 = order[rest1.id] ?? Int.max
    let order2 = order[rest2.id] ?? Int.max

    return order1 < order2

如果您有多个餐厅 ID,这可能比重复使用 index(of:) 来计算映射更有效。您的餐厅数组越大,调用index(of:) 的次数就越多(因为sortO(n log n)),因此对index(of:) 的调用次数会随着餐厅数组大小的增加而迅速增长。 index(of:) 是基于 id 数组大小的 O(n) 操作。 id 数组越大,index(of:) 变得越慢。

【讨论】:

“这样更有效率……”?在示例中,restaurantIDs 很短,当然可以更长,但鉴于它的 ID 列表是要在数据库中查找的 iOS 应用程序,我们可能会猜到它并没有那么大。 dict 需要在插入和查找时进行动态分配和哈希计算。数组的index(of:) 可能需要偏移计算(可能只是迭代)并且将平均 n/2 比较。这两种方法可能更快,取决于数据,但它真的很重要吗?你确定这不是过早的优化吗? (我承认,我考虑过一个口述,我们都想不接吻 ;-)) @CRD,两种方式都有优点。如果 OP 真的只有 3 个 id,那么字典就大材小用了。餐厅 ID 列表是提前知道的,因此可以在那时创建字典,而不是等待餐厅被读取。在排序中,相同的查找会重复发生,所以n/2 加起来。我不认为这是过早的优化。它正在考虑一种可以很好地扩展的算法。使用 6 位数的餐厅 ID,可能有 3 个以上。 编辑很好,但你应该仍然有一个“可能”在那里;-) 我知道这最终会比index(of:) 更有效率。我心中唯一剩下的问题是盈亏平衡点在哪里。如果可以提前创建字典,那么盈亏平衡点就更低了。 我们在这里跳舞,我说“可能”,你说“最终”;-) 你明白了我的原意,但表达得不好,很高兴与你交谈。【参考方案3】:

一种方法是使用flatMap 遍历restaurantIds 数组,并返回returnedRestaurant 数组中id 与restaurantIds 中当前索引处的id 匹配的第一个元素。此函数返回一个新的排序数组,并且不会改变 returnedRestaurant 数组。

let sortedRestaurants = restaurantIds.flatMap id in
    returnedRestaurant.filter$0.restaurantId == id .first

【讨论】:

如果你在 restaurantIds 上使用 flatmap 函数,它会展平 restaurantIds 数组,但我们不想展平数组,我们只想根据 restaurantIds 数组使用的顺序对返回的餐厅进行排序每个餐厅内的 id。我还没有尝试过,但是如果您认为它会起作用,我会尝试一下。 只要你没有重复的 restaurantIds 就可以了。如果您确实有重复 ID,那么这会删除除找到的第一家餐厅之外的所有餐厅。 @vacawama 你是对的,我认为 id 是唯一的。但是这个解决方案可以很容易地修改为也可以使用重复的 id。

以上是关于【JS】数组对象自定义排序的主要内容,如果未能解决你的问题,请参考以下文章

Android排序自定义对象数组

使用内部对象的实例变量的值对自定义对象数组进行排序

js简单对象List自定义属性排序

31Arrays数组排序(续)——自定义排序

使用usort和自定义比较函数的多维数组/对象排序

sort方法和自定义比较器的写法