2013-07-06 53 views
-1

的组等同的元件是否有一个的JavaScript的CoffeeScript函数(或也许的延伸突出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] ] 
+1

你能等价功能扩展到比较功能,并使用排序? (不要紧,什么样的顺序比较函数产生的,只要它是自洽的。) – user2357112

+2

另外,你知道这会在时间中的二次等价类的数量运行,对不对?如果你能以某种方式为每个等价类生成一个身份代码并使用'groupBy',它会快得多。 – user2357112

+0

请不要在标题中添加标签,这是标签的用途。 – elclanrs

回答

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/

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”功能,以确保价值的明确等价为我的使用情况。

+0

为什么选择倒票? (以及为什么对这个问题进行反对票?) –