Javascript 多维数组的排序顺序跨浏览器兼容并与;“自然情况”;
我需要为我的web应用程序复杂地排序一些较大的数组(1000-2000个键)。我在Safari 12.0/FF 66.0中使用了一点,但chrome 74.0似乎完全做了其他事情 我要排序的序列-不区分大小写,使用自然大小写:Javascript 多维数组的排序顺序跨浏览器兼容并与;“自然情况”;,javascript,sorting,multidimensional-array,cross-browser,natural-sort,Javascript,Sorting,Multidimensional Array,Cross Browser,Natural Sort,我需要为我的web应用程序复杂地排序一些较大的数组(1000-2000个键)。我在Safari 12.0/FF 66.0中使用了一点,但chrome 74.0似乎完全做了其他事情 我要排序的序列-不区分大小写,使用自然大小写: 1. "scene" 2. "shot" 3. "take" 4. "name" 这些值中的每一个都可以是字符串(例如4、4b或4-PUüöä!)或“未定义”,看起来可能类似于: [ {"scene": "1", "shot": "1", "take"
1. "scene"
2. "shot"
3. "take"
4. "name"
这些值中的每一个都可以是字符串(例如4
、4b
或4-PUüöä!
)或“未定义”,看起来可能类似于:
[
{"scene": "1", "shot": "1", "take": "4", "name": "A031C006_170718_R1W0"},
{"scene": "8", "shot": "8", "take": "4", "name": "A020C004_170716_R1W0"},
{"scene": "1", "shot": "1", "take": "10", "name": "A031C013_170718_R1W0"},
{"scene": undefined, "shot": undefined, "take": undefined, "name": "A001C549_190226_R04Q"},
{"scene": "2", "shot": "2", "take": "1", "name": "A008C010_170715_R1W0"},
{"scene": "5", "shot": "5", "take": "1", "name": "A015C005_170716_R1W0"},
{"scene": "3", "shot": "3", "take": "7", "name": "A002C003_170714_R1W0"},
{"scene": "5", "shot": "5", "take": "5", "name": "A021C005_170716_R1W0"},
{"scene": "5", "shot": "5", "take": "9", "name": "A024C006_170717_R1W0"},
{"scene": "1", "shot": "1", "take": "3", "name": "A004C006_170714_R1W0"},
{"scene": "1-b", "shot": "1", "take": "3", "name": "A004C007_170718_R1W0*"},
{"scene": "5", "shot": "5PU", "take": "6", "name": "A021C005_170716_R1W0*"},
]
如果关键点场景
不存在,请排序到末尾并按“名称”排序
这是vue.js项目的一部分,我希望不用额外的库就能完成
到目前为止,这是我的函数。我使用localCompare()
将4a
与4
或4ä
进行比较。我很确定这非常慢,可以做得更好
sortedFiles = sortClips(files)
sortClips(clips) {
let firstBy=(function(){function e(f){f.thenBy=t;return f}function t(y,x){x=this;return e(function(a,b){return x(a,b)||y(a,b)})}return e})();
let options = {
numeric: true,
sensitivity: 'base',
ignorePunctuation: true
};
clips.sort(
firstBy(function (v1, v2) {
if (!v1.scene) {
return v1.name.localeCompare(v2.name, undefined, options);
}
return v1.scene.localeCompare(v2.scene, undefined, options);
})
.thenBy(function (v1, v2) {
if (!v1.shot) return -1;
return v1.shot.localeCompare(v2.shot, undefined, options);
})
.thenBy(function (v1, v2) {
if (!v1.take) return -1;
return v1.take.localeCompare(v2.take, undefined, options);
})
);
return clips;
},
原始数据(场景、快照、拍摄、名称):
Firefox/safari分类:
8 8 4 A020C004_170716_R1W0
1 1 4 A031C006_170718_R1W0
1 1 10 A031C013_170718_R1W0
undefined undefined undefined A001C549_190226_R04Q
5 5 1 A015C005_170716_R1W0
5 5 9 A024C006_170717_R1W0
3 3 7 A002C003_170714_R1W0
5 5 5 A021C005_170716_R1W0
1 1 3 A004C006_170714_R1W0
2 2 1 A008C010_170715_R1W0
1-b 1 3 A004C007_170718_R1W0*
5 5PU 6 A021C005_170716_R1W0*
Chrome的分类不同:
5 5 1 A015C005_170716_R1W0
5 5 9 A024C006_170717_R1W0
3 3 7 A002C003_170714_R1W0
5 5 5 A021C005_170716_R1W0
1 1 3 A004C006_170714_R1W0
undefined undefined undefined "A001C549_190226_R04Q"
8 8 4 A020C004_170716_R1W0
1 1 4 A031C006_170718_R1W0
1 1 10 A031C013_170718_R1W0
2 2 1 A008C010_170715_R1W0
1-b 1 3 A004C007_170718_R1W0*
5 5PU 6 A021C005_170716_R1W0*
目标:
1 1 3 A004C006_170714_R1W0
1 1 4 A031C006_170718_R1W0
1 1 10 A031C013_170718_R1W0
1-b 1 3 A004C007_170718_R1W0*
2 2 1 A008C010_170715_R1W0
3 3 7 A002C003_170714_R1W0
5 5 1 A015C005_170716_R1W0
5 5 5 A021C005_170716_R1W0
5 5PU 6 A021C005_170716_R1W0*
5 5 9 A024C006_170717_R1W0
8 8 4 A020C004_170716_R1W0
undefined undefined undefined A001C549_190226_R04Q
我怎样才能按我想要的分类呢
更新:我已经包括了边缘案例:
- 场景“1-b”当键为“场景”时,添加的字符“-b”应排序在场景“1”的所有元素之后
- Shot“5PU”当键为“Shot”或“take”时,应忽略添加的字符“PU”
var options={numeric:true,sensitivity:'base',ignorepercentration:true},
数组=[{场景:“1”,镜头:“1”,镜头:“4”,namw:“A031C006_170718_R1W0”},{场景:“8”,镜头:“8”,镜头:“4”,名称:“A020C004_170716_R1W0”},{场景:“1”,镜头:“1”,镜头:“10”,名称:“A031C013_170718_R1W0”},{场景:未定义,镜头:未定义,镜头:未定义,镜头:未定义,名称:“A001C549_R04Q”},{场景:“2”,镜头:“2”,镜头:“名称:{A008C010_170715_R1W0“},{场景:“5”,镜头:“5”,镜头:“1”,名字:“A015C005_170716_R1W0”},{场景:“3”,镜头:“3”,镜头:“7”,名字:“A002C003_170714_R1W0”},{场景:“5”,镜头:“5”,名字:“A021C005_170716_R1W0”},{场景:“5”,镜头:“5”,镜头:“9”,名字:“A024C003_170717_R1W0”},镜头:“1”,镜头:“1,{A004C006_170714_R1W0“},{场景:“1-b”,镜头:“1”,镜头:“3”,名字:“A004C007_170718_R1W0*”},{场景:“5”,镜头:“5PU”,镜头:“6”,名字:“A021C005_170716_R1W0*”},
按键=[“场景”、“快照”、“拍摄”、“名称”];
array.sort((a,b)=>{
var结果;
key.some(k=>result=String(a[k]).localeCompare(b[k],未定义,选项));
返回结果;
});
console.log(数组);
。作为控制台包装{max height:100%!important;top:0;}
您的排序函数不稳定
if (!v1.shot) return -1;
如果
v2
也没有“shot”属性该怎么办?您的排序函数应该总是为sort(a,b)
和sort(b,a)
返回相反的结果,而您的却没有。因为Chrome似乎使用了另一个排序器,它只在这个浏览器中失败(现在,算法可能会在将来发生变化)这是一个复杂的问题。首先是代码,然后是解释:
const场景=[
{“场景”:“1”,“拍摄”:“1”,“拍摄”:“4”,“姓名”:“A031C006_170718_R1W0”},
{“场景”:“8”,“拍摄”:“8”,“拍摄”:“4”,“姓名”:“A020C004_170716_R1W0”},
{“场景”:“1”,“拍摄”:“1”,“拍摄”:“10”,“姓名”:“A031C013_170718_R1W0”},
{“场景”:未定义,“拍摄”:未定义,“拍摄”:未定义,“名称”:“A001C549_190226_R04Q”},
{“场景”:“2”,“拍摄”:“2”,“拍摄”:“1”,“姓名”:“A008C010_170715_R1W0”},
{“场景”:“5”,“拍摄”:“5”,“拍摄”:“1”,“姓名”:“A015C005_170716_R1W0”},
{“场景”:“3”,“拍摄”:“3”,“拍摄”:“7”,“姓名”:“A002C003_170714_R1W0”},
{“场景”:“5”,“拍摄”:“5”,“拍摄”:“5”,“姓名”:“A021C005_170716_R1W0”},
{“场景”:“5”,“拍摄”:“5”,“拍摄”:“9”,“姓名”:“A024C006_170717_R1W0”},
{“场景”:“1”,“拍摄”:“1”,“拍摄”:“3”,“姓名”:“A004C006_170714_R1W0”},
]
常量比较字符串=(a,b)=>{
if(`${a}`!==a)返回1
if(`${b}`!==b)返回-1
返回a.localeCompare(b,未定义{
数字:对,
敏感度:'base',
忽略标点符号:正确
})
}
常量排序=[
“场景”,
"射击",,
“拿”,
“姓名”,
]
常量全局比较=(a,b)=>
排序。减少((acc,键)=>{
如果(acc==0)返回比较器字符串(a[键]、b[键])
返回acc
}, 0)
scenes.sort(globalCompare)
console.log(scenes)
的确如此!感谢您的洞察力,帮助我思考这个案例。这几乎可以完美地工作!谢谢!唯一的问题是,仅定义了“name”的数组元素将位于开头而不是结尾,对吗?是否存在“result”的可能性“是否null
?我刚刚意识到我遗漏了一些边缘案例。我已经用场景“1-b”更新了我的问题,并拍摄了“5-PU”,它们被排序到数组的末尾。你有什么想法吗?我得到了一个不同的结果'5PU'
在'5'
之后,因为'5'
较短。这是正确的,但我的用例需要这种排序,在处理键“shot”和“take”时基本上忽略字母:5 1/5 5 5/5 5PU 6/5 5 9
但使用键“scenes”a-b
,移动到所有场景的末尾1
,在场景2
之前:1 1 4/1 1 10/1-b 1 3/2 2 1
问题是,您不能(随机)关闭一些字母,因为您需要更多的规则来清理值。谢谢!这也很有效。我接受了Nina Scholz的答案,代码行数减少了:),但我刚刚意识到我遗漏了一些边缘案例。我已经用场景“1-b”更新了我的问题,并拍摄了“5-PU”,它们被排序到数组的末尾。你有什么想法吗?
if (!v1.shot) return -1;