【问题标题】:Sorting not being applied in a list of objects排序未应用于对象列表
【发布时间】:2020-02-28 12:16:34
【问题描述】:

我正在对一个对象数组进行排序,排序函数似乎对数组没有任何结果。所以它返回相同的列表。

我将数组和排序函数导出到窗口并手动执行它们,然后得到的数组排序良好。

import { connect } from "react-redux"

import DestinationsGallery from "./destinationsGallery"

import DestinationFilter from "./functions/filter"
import WindPoint from "./functions/windPoint"
import {sortCosts,sortWind, sortName} from "./functions/sort"

const getSelectedDestinations = ( catalog, filter ) => { 
    let paramCatalog = null 
    let paramSorted = null

    if (catalog) {
        paramCatalog =  catalog
            .map(spot => WindPoint(spot,filter))
            .filter( item => DestinationFilter( item,filter ) )
            .sort( ( a,b ) => a.name.localeCompare( b.name ) )


        window.catalog = paramCatalog
        window.sortCosts = sortCosts
        window.sortWind = sortWind
        window.sortName = sortName

        console.log("Unsorted",paramCatalog)    
        paramSorted = paramCatalog.sort( sortName )
        console.log( "Sorted name",paraSorted, paramCatalog.sort( sortName ) )


        let paraSorted = paramCatalog.sort( sortWind )
        console.log( "Sorted wind",paraSorted )
    }
    return paramSorted
}

export default connect( store => ({
    destinations: getSelectedDestinations(store.kiteSpots.catalog.list, store.kiteSpots.filter),
    filter: store.kiteSpots.filter,
}),null)(DestinationsGallery)

我的排序功能是:

export const sortCosts = ( a,b ) => ( a.data.CostsRank > b.data.CostsRank? 1 : -1 )  
export const sortWind = ( a,b ) => ( a.windPoint.probability > b.windPoint.probability ? 1 : -1 ) 
export const sortName = ( a,b ) => { return a.name > b.name ? 1 : -1 }

所以我只想输出列表是正确的

【问题讨论】:

  • @NinaScholz 他们没有返回布尔值
  • @PatrickRoberts 是的。但它省略了一个值 - 在这种情况下,相同的值为零。所以它也适用于此。 (但这可能不是问题的解决方案。)
  • 如果它们相等,则它们是否被交换都没有关系。返回布尔值的问题是函数永远不能指示交换。
  • 实际上该函数在浏览器窗口上运行,但我不明白为什么在我的代码中它们不会产生排序结果。

标签: javascript arrays reactjs sorting gatsby


【解决方案1】:

您可以尝试使用String.prototype.localeCompare 来比较字符串。 See MDN.

const x = [
  { name: "James"},
  { name: "Zeb"},
  { name: "Annie"},
  { name: "Michaèl"},
  { name: "James"},
];

console.log( x.slice(0).sort( (a, b) => a.name.localeCompare(b.name) ) );
// include value equality
console.log( x.slice(0).sort( (a, b) => -(a.name < b.name) || +(a.name > b.name)) );

或者在比较中包含可能的值相等:

a.name &gt; b.name ? 1 : a.name &lt; b.name ? -1 : 0) 或(见 cmets)

-(a.name &lt; b.name) || +(a.name &gt; b.name)

或者(为了性能)你可以使用Intl.Collatorsee MDN和下一个sn-p)

const intlCollator = new Intl.Collator("de", {sensitivity: "variant"});
console.log( 
  [
    { name: "Anna"},
    { name: "Michiel"},
    { name: "Desiré"},
    { name: "Siënna"},
    { name: "Jøn"},
    { name: "Mariêke"},
    { name: "José"},
    { name: "Anna"},
    { name: "Renée"},
    { name: "Désirée"},
  ].sort( (a, b) => 
      intlCollator.compare(a.name, b.name) )
);
.as-console-wrapper { top: 0; max-height: 100% !important; }

【讨论】:

  • (a, b) =&gt; a.name &gt; b.name ? 1 : -1 也适用于这个特定的示例。 localeCompare 唯一可以改进排序的地方是,如果需要将 èfz 之间的无重音字母进行比较
  • @PatrickRoberts 当然,将其包含在答案中。 localeCompare 有点短,也可以用于比较重音/变音等,也可以返回 1、-1 或 0。
  • 如果你要包括不等式方法,我可以建议(a, b) =&gt; -(a.name &lt; b.name) || +(a.name &gt; b.name)吗?此外,localeCompare狗慢,所以这也可能是一个考虑因素。
【解决方案2】:

如果它符合您的预期,此代码不会对目录数组进行变异(排序),只有参数目录将被排序,因为排序应用于目录的映射和过滤结果,两者都返回新的数组实例。

如果您发布更多代码和源数据,我们可能会发现问题所在。

也就是说,您不应该使用数学运算符以这种方式比较字符串,因为它的行为可能与您预期的不同。

This discussion from stackoverflow 解释了一些差异。简而言之,代码点顺序(与 > 比较时使用)与实际字母顺序不同。

此外,比较函数的返回值应该是 1、-1 或 0,因为有时不交换相等的值很重要。

例如,通过允许交换相等的比较值对 [0,0,1,1,2,2,3,3] 进行排序并不重要。

但是排序 [{ name: 'foo', value: 0},{ name: 'bar', value: 0},{ name: 'fuu', value: 1},{ name: 'ber', value : 1}] 根据值可能会在不理想时更改原始数组的顺序。

确实,原生排序的旧实现不关心相等的比较值,并且可能无论如何都有顺序,但现在没有实现尊重不修改已排序数组的约定。

如果您关心 unicode 字符串的字母顺序,请尝试使用 String.prototype.localeCompare

如果您正在比较数字(例如 a 和 b),并且您不必处理 NaN 或无穷大或未定义,则它更正确并且需要更少的本机指令来返回 a-b 以进行升序和b-a 用于降序。

【讨论】:

  • because not swaping equal values sometimes matter 如果它们相等,那没关系
  • 使用排序回调时,您可以对对象数组进行排序,并使用对象的一个​​属性作为实际排序值。如果您根据此属性交换相等的值,例如您可以更改已排序数组的初始顺序。所以是的,在某些情况下它确实很重要。相等的排序值何时严格意味着相等的值并不重要,这绝对不是每次都正确。
  • 如果属性是唯一的排序标准,那么整个对象仍然被认为是相等的,只比较属性。此外,在 ECMAScript 2020 之前,原生的 sort() 方法甚至不能保证稳定性无论如何,所以回调是否能够返回 0 并不重要。
  • 相等的排序标准并不严格意味着相等的值。如果你不考虑它,你可能会引入不良行为
  • 我遇到了本地排序服务器端的不稳定,我求助于在旧节点中重新实现冒泡排序:/ 尽管如此,交换相等比较可能是危险的且效率较低。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多