在JavaScript中如何像Python一样比较两个列表?
我刚接触JavaScript,但对Python比较熟悉。在Python中,我得到了这个输出:
In [1]: [1,9,[5,4,2]] > [1,9,[14,5,4]]
Out[1]: False
在JavaScript中:
> [1,9,[5,4,2]] > [1,9,[14,5,4]]
true
看起来数组在比较之前被转换成了字符串。
现在我想自己写一个函数,遍历数组并比较每个元素。我想出了这个CoffeeScript代码:
compare_list = (a, b)->
if typeof a == "object" and typeof b != "object"
return 1
else if typeof a != "object" and typeof b == "object"
return -1
else if typeof a != "object" and typeof b != "object"
if a > b
return 1
else if a < b
return -1
else
return 0
else if typeof a == "object" and typeof b == "object"
for i in [0...a.length]
if i > (b.length-1)
return 1
tmp = compare_list a[i], b[i]
if tmp != 0
return tmp
if b.length > a.length
return -1
return 0
这个方法可以工作,但我觉得typeof a == "object"
这一部分看起来不太对。有没有更简单、更好、更稳健的解决方案?
谢谢你的帮助。
5 个回答
1
我尝试实现一个JavaScript函数 compareArrays
,它的功能类似于Python中的数组比较:
function compareArrays(a, b) {
var aIsArray = Array.isArray(a),
bIsArray = Array.isArray(b),
cmp = 0;
if (!aIsArray || !bIsArray) {
throw new Error('Can\'t compare array to non-array: ' + a + ', ' + b);
}
_.find(a, function (aElem, index) {
var bElem = b[index];
if (Array.isArray(aElem) || Array.isArray(bElem)) {
cmp = compareArrays(aElem, bElem);
} else {
cmp = (aElem > bElem) - (aElem < bElem);
}
if (cmp !== 0) {
return true;
}
});
return cmp;
}
这个函数使用了Underscore库来遍历数组,并且通过递归的方式来处理嵌套数组。
你可以查看我的示例,里面包含了一些基本的测试用例。
测试结果
[1,9,[5,4,2]] < [1,9,[14,5,4]]
[1,[1]] can't be compared to [1,1]
[1,[2]] > [1,[1]]
[2] > [1]
[1] == [1]
[] == []
4
这个算法基本上和之前的差不多,只是避免使用了 typeof
操作符,并在 for
循环中做了一点小技巧,这样就不用每次都检查数组的长度了:
cmp = (a, b) -> (a > b) - (a < b)
cmpArray = (a, b)->
aIsArray = Array.isArray a
bIsArray = Array.isArray b
return cmp a, b if not aIsArray and not bIsArray
return -1 if not aIsArray and bIsArray
return 1 if aIsArray and not bIsArray
# Both are arrays.
len = Math.min a.length, b.length
for i in [0...len] by 1
if tmp = cmpArray a[i], b[i]
return tmp
a.length - b.length
可惜的是,CoffeeScript 不提供任何形式的模式匹配。如果有的话,这段代码会更简洁。你可以用 switch
语句来模拟一种简单的模式匹配,假如你想这样做的话:
cmpArray = (a, b)->
switch "#{Array.isArray a},#{Array.isArray b}"
when 'false,false' then (a > b) - (a < b) # Compare primitives.
when 'false,true' then -1
when 'true,false' then 1
else
len = Math.min a.length, b.length
for i in [0...len] by 1
if tmp = cmpArray a[i], b[i]
return tmp
a.length - b.length
不过,这样写在 CoffeeScript 中并不是特别符合习惯。如果 CoffeeScript 支持某种模式匹配,我肯定会选择这种写法,因为它看起来很简洁,只用了一行表达式,也不太依赖于提前返回的方式。
1
我也在尝试解决同样的问题,最后只想到了一种自定义的解决办法。你可以在这里查看:https://gist.github.com/ruxkor/2772234
因为在比较对象时,JavaScript会自动把字符串转换成其他类型,所以我觉得有必要使用一个自定义的比较函数,来模拟Python的比较方式。