我对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"
部分看起来不正确。是否有更简单/更好/更强大的解决方案?
感谢您的帮助。
答案 0 :(得分: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 :(得分:1)
试图解决同样的问题,我也只提出了一个自定义解决方案。 https://gist.github.com/ruxkor/2772234
由于Javascript在比较对象时使用字符串强制,我认为有必要使用自定义比较函数来模拟Python行为。
答案 2 :(得分:1)
让我们简约:
function compare(a, b) {
if (a instanceof Array && b instanceof Array) {
for (var r, i=0, l=Math.min(a.length, b.length); i<l; i++)
if (r = compare(a[i], b[i]))
return r;
return a.length - b.length;
} else // use native comparison algorithm, including ToPrimitive conversion
return (a > b) - (a < b);
}
(使用instanceof
进行数组检测,请参阅this article进行讨论)
如果要使对象始终大于基元,可以将最后一行更改为
return (typeof a==="object")-(typeof b==="object") || (a>b)-(a<b);
答案 3 :(得分: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迭代数组,并递归处理嵌套数组。
请参阅我的fiddle,其中包含原始测试套件。
[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 :(得分:0)
它非常丑陋,但这似乎可以完成这项工作:
var compareLists = function compare(listA, listB) {
if (Array.isArray(listA)) {
if (Array.isArray(listB)) {
if (listA.length == 0) {
if (listB.length == 0) {
return 0;
} else {
return -1;
}
} else {
if (listB.length == 0) {
return +1;
} else {
return compare(listA[0], listB[0]) ||
compare(listA.slice(1), listB.slice(1));
}
}
} else {
return -1; // arbitrary decision: arrays are smaller than scalars
}
} else {
if (Array.isArray(listB)) {
return +1; // arbitrary decision: scalars are larger than arrays
} else {
return listA < listB ? -1 : listA > listB ? + 1 : 0;
}
}
};
compareLists([1, 9, [5, 4, 2]], [1, 9, [14, 5, 4]]); // -1
compareLists([1, 9, [5, 4, 2]], [1, 9, [5, 4]]); // +1
compareLists([1, 9, [5, 4, 2]], [1, 9, [5, 4, 2]]); // 0
根据您的环境,您可能希望填充Array.isArray
:
if (!Array.isArray) {
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
}