-1

是否有一个javascriptcoffeescript函数(或者可能是下划线 groupBy函数的扩展)接收数组等价比较器(具有两个参数的布尔函数,而不仅仅是一个参数)作为参数,并根据这个等价对数组元素进行分组比较器?

作为我想要的一个例子:

areEquivalent = (p1, p2) ->
  p1.birthYear == p2.birthYear and
  p1.birthPlace == p2.birthPlace and
  p1.gender == p2.gender

p1 = {name:'Anna', birthYear: 1990, birthPlace: 'Alaska', gender: 'female', hasCar: true, hasChildren: false}
p2 = {name:'John', birthYear: 1990, birthPlace: 'Alaska', gender: 'male', hasCar: true, hasChildren: false}
p3 = {name:'Dora', birthYear: 1980, birthPlace: 'Hawaii', gender: 'female', hasCar: true, hasChildren: true}
p4 = {name:'Lumi', birthYear: 1980, birthPlace: 'Hawaii', gender: 'female', hasCar: false, hasChildren: false}
p5 = {name:'Jack', birthYear: 1990, birthPlace: 'Alaska', gender: 'male', hasCar: false, hasChildren: false}

console.log areEquivalent p1, p2
# false
console.log areEquivalent p3, p4
# true

people = [p1, p2, p3, p4, p5]

console.log _.groupEquivalentObjects(people, areEquivalent)
# [ [p1], [p2,p5], [p3,p4] ]
4

2 回答 2

4

你不能只通过_.groupBy()和表达来正确区分你的输入吗?

p1 = {name:'Anna', birthYear: 1990, birthPlace: 'Alaska', gender: 'female', hasCar: true, hasChildren: false}
p2 = {name:'John', birthYear: 1990, birthPlace: 'Alaska', gender: 'male', hasCar: true, hasChildren: false}
p3 = {name:'Dora', birthYear: 1980, birthPlace: 'Hawaii', gender: 'female', hasCar: true, hasChildren: true}
p4 = {name:'Lumi', birthYear: 1980, birthPlace: 'Hawaii', gender: 'female', hasCar: false, hasChildren: false}
p5 = {name:'Jack', birthYear: 1990, birthPlace: 'Alaska', gender: 'male', hasCar: false, hasChildren: false}

people = [p1, p2, p3, p4, p5]

groups = _.groupBy(people, (x) -> '' + x.birthYear + x.birthPlace + x.gender)

console.log groups

http://jsfiddle.net/vKz6r/

于 2013-07-07T00:41:33.307 回答
0

谢谢大家的回答和建议。

目前我实施了这个不是非常理想的解决方案:

# Modifies the received array, by removing all the elements equivalent to the first one,
# and returning them in a separate array
extractAllObjectsEquivalentToFirst = (array, areEquivalent) ->
  return [] if array.length == 0
  first = array.shift()
  equivalent = [first]
  different = []
  while array.length > 0
    elem = array.shift()
    if areEquivalent(elem,first)
      equivalent.push elem
    else
      different.push elem
  array[..] = different
  return equivalent

groupEquivalentObjects = (array, areEquivalent) ->
  arrayClone = array[..]
  groups = []
  previous = arrayClone.length
  while arrayClone.length > 0
    groups.push extractAllObjectsEquivalentToFirst(arrayClone, areEquivalent)
    if arrayClone.length >= previous
      console.warn "Array length did not decrease!"
      arrayClone = []
    previous = arrayClone.length
  return groups

但确实更好的解决方案是为项目定义某种hashCode()函数,并将该函数作为参数传递给_.groupBy()

在我当前的用例中,我需要比较的一些对象属性实际上是数组,为此我需要在等价比较器中使用_.isEqual() 。

目前我懒得想办法定义一个“hashCode”函数,以确保我的用例的值明确等价。

于 2013-07-07T01:24:32.990 回答