【问题标题】:Is there an idiomatic way to test array equality in Coffeescript?有没有一种惯用的方法来测试 Coffeescript 中的数组相等性?
【发布时间】:2014-03-10 16:15:23
【问题描述】:

表达式

[1, 2, 3] == [1, 2, 3]

Coffeescript 中计算为 false,但是否有一种简洁、惯用的方法来测试数组是否相等?

【问题讨论】:

  • 我对coffeescript了解不多,但您似乎正在使用==而不是单个数组值来测试对象的相等性。
  • 有人应该注意到,coffeescript 中的== 在javascript 中被评估为===

标签: arrays coffeescript equality


【解决方案1】:

如果您正在处理数字数组,并且您知道数组中没有空值或未定义值,则可以将它们作为字符串进行比较:

a = [1, 2, 3]
b = [1, 2, 3]

console.log "#{a}" is "#{b}" # true
console.log '' + a is '' + b # true

但是请注意,一旦您开始比较其他非数字的数组,这将中断:

a = [1, 2, 3]
b = ['1,2', 3]

console.log "#{a}" is "#{b}" # true

如果您想要更健壮的解决方案,可以使用Array#every

arrayEqual = (a, b) ->
  a.length is b.length and a.every (elem, i) -> elem is b[i]

console.log arrayEqual [1, 2, 3], [1, 2, 3]   # true
console.log arrayEqual [1, 2, 3], [1, 2, '3'] # false
console.log arrayEqual [1, 2, 3], ['1,2', 3]  # false

请注意,它首先比较数组的长度,因此 arrayEqual [1], [1, 2, 3] 不会返回 true。

【讨论】:

  • 我喜欢 Array::every 解决方案,但 IE
  • @PirateRob 是的,这可能是个问题。我个人不再评论“注意这在 IE 中可能不起作用”,因为很多时候它没有意义;有很多移动 JS 开发,Node.js 之类的,所以,如果没有以前的信息,我什至不会评论 IE 兼容性。如果您确实需要关心 IE 但仍想使用更新的 JS 东西,您可以只降低 IE 用户的体验,并有条件地为所有人添加一个“shim”,例如 es5-shim那些好东西:)
  • 另外,您可以使用 Underscore 的 every 实现,这将以非常低的成本保证跨浏览器的兼容性:)
【解决方案2】:

如果您不介意引入Underscore.js 依赖项,您可以使用它的一些实用程序。它不是很优雅,但我想不出用普通的咖啡脚本更简单的方法:

a = [ 1, 2, 3 ]
b = [ 1, 2, 3 ]
equal = a.length == b.length and _.all( _.zip( a, b ), ([x,y]) -> x is y )

【讨论】:

  • 我能想到的唯一改进就是使用coffeescript的解构赋值:_.all(x is y for [x, y] in _.zip( a, b ))
  • 注意_.all 需要一个迭代器函数。这个例子breaks 在 Firefox 和 Chrome 中对我来说都是现在的样子(“迭代器不是函数”在 FF 中抛出)。幸运的是,fix it: _.all _.zip(a, b), ([x, y]) -> x is y 很容易 :)
  • 不幸的是,使用_.zip 将导致此解决方案比较[1, 2, 3, undefined][1, 2, 3] as equal :(
  • @epidemian 好点——显然我在发布之前没有对此进行测试。我会解决的。
  • 我希望人们能改掉使用 _ 的习惯——当你进入节点命令行时它会中断...
【解决方案3】:

我不认为这是惯用的,但这是一种无需添加额外库的方式:

a = [1, 2, 3, 4]
b = [22, 3, 4]

areEqual = true
maxIndex = Math.max(a.length, b.length)-1
for i in [0..maxIndex]
    testEqual = a[i] is b[i]
    areEqual = areEqual and testEqual

console.log areEqual

更简洁的方法是使用 JavaScript 的 reduce() 函数。这有点短,但我不确定所有浏览器都支持减少。

a = [1, 3, 4, 5]
b = [1, 3, 4, 5]

maxIndex = Math.max(a.length, b.length)-1
areEqual = true
[0..maxIndex].reduce (p, c, i, ar) -> areEqual = areEqual and (a[i] is b[i])

console.log "areEqual=#{areEqual}"

【讨论】:

    【解决方案4】:

    下面的效果很好,不需要依赖:

    arrayEqual = (ar1, ar2) ->
      JSON.stringify(ar1) is JSON.stringify(ar2)
    

    【讨论】:

      【解决方案5】:

      我是Sugar.js 的忠实粉丝。如果你碰巧在使用它:

      a = [1, 2, 3]
      b = [1, 2, 3]
      Object.equal(a, b)
      

      【讨论】:

        【解决方案6】:

        如果数组具有相同的长度并且具有相同索引的所有值具有相同的值,则此函数返回true。如果任一参数不是数组,则会引发错误。

        isArray = Array.isArray || (subject) ->
            toString.call(subject) is '[object Array]'
        
        compareArrays = (a, b) ->
            unless isArray(a) and isArray b
                throw new Error '`arraysAreEqual` called with non-array'
        
            return false if a.length isnt b.length
        
            for valueInA, index in a
                return false if b[index] isnt valueInA
        
            true
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-14
          相关资源
          最近更新 更多