使用Groovy在纯功能性的方式解决一个问题排名

问题描述 投票:0回答:3

我已经解决了,通过的票数位居水果的问题。不幸的是,我要解决的问题,纯粹功能性的方式没有突变的rankPosition变量。这里是我的解决方案:

  def fruits=[
 [name:'apple',       votes:120 , ranking:null ],
 [name:'banana',      votes:200,  ranking: null],
 [name:'apricot',     votes:66,   ranking:null ],
 [name:'pear',        votes:84,   ranking:null],
 [name:'kiwi',        votes:77,   ranking:null],
 [name:'plum',        votes:66,   ranking:null],
 [name:'berry',       votes:120,  ranking:null],
 [name:'pineapple',   votes:50,   ranking:null],
 [name:'grapes',      votes:200,  ranking:null]

]

    def rankPosition= 1
    def groupedByVotes = fruits.groupBy {it.votes }

     println "Ratings $groupedByVotes"

    def finalResults=groupedByVotes.sort().each { votes, items ->

        items.each { it.ranking = rankPosition }

        rankPosition += items.size()
    } 

    println "Final Results are $finalResults"

我怎样才能解决这个问题,而不需要声明一个变量rankingPosition外部的关闭和变异的状态。请指出,这种解决方案的工作,但因为我已经知道我不应该做这种方式。我希望能够用正确的排序,以填补排名。该注射功能确实积累,但我不知道如何将它的方式相结合,也与设置在注入累积值的排名。

我只是坚持,只是似乎不能够推理这一个。我下面用注射的尝试,根本没有工作。也许没有办法在一个纯粹的功能性的方式来做到这一点,我thsn尝试更好。

def res= groupedByVotes.collectEntries{votes, list1->
println "list class $list1"
def r= list1.inject(0){acc,l-> acc+l.size()}
 list1.each{it.ranking=r}
 println "$r"
 [(votes): list1]
} 
println "$res"

我任何人都可以,然后我将不胜感激您的解决方案或只承担我的尝试是解决这一个最为现实的途径。

groovy functional-programming ranking
3个回答
0
投票

这是一个纯粹的功能的解决方案。它留下的地图不变的初始地图,并产生一个新问题:

def results = groupedByVotes.sort().inject(new Tuple(1, [:]), { acc, entry ->
    def newRank = acc[0] + entry.value.size()
    def newValue = entry.value.collect { [*:it, ranking:acc[0]] }
    return new Tuple(newRank, [*:acc[1], (entry.key):newValue] )
})
finalResults = results[1]

0
投票

我可能没有很好地解释什么,我想要的目的。计算排名之后,我想插在列表中的各个元素的值。以下是我想出了:

  def sortedFruits= fruits.sort{f1, f2 -> f1.votes <=> f2.votes}

  (0..sortedFruits.size()-1)
   .each{ i ->
    if(i==0){
    sortedFruits.get(i).ranking=1
    }else if(sortedFruits.get(i-1).votes==sortedFruits.get(i).votes){
      sortedFruits.get(i).ranking=i
   }else{
    sortedFruits.get(i).ranking=i+1
  }
   if(i<sortedFruits.size()){
     def f= sortedFruits.get(i)
      println "${f}"
  }

}

 println "Sorted Fruits are $sortedFruits"

最后的结果看起来像排序水果是[[名:柠檬,票:20,排名:1],[名称:番石榴,票:20,排名:1],[名称:菠萝,票:50,排名:3] [姓名:杏,票:66,排名:4],[名称:李子,票:66,排名:4]等。


0
投票

你可以试试这个:

def results = groupedByVotes.sort()
    .inject(new Tuple(1, []), { acc, entry ->
        entry.value.each { it.ranking = acc[0] }
        return new Tuple(acc[0] + entry.value.size(), acc[1] << entry.value)
    })

finalResults = results[1]

在折叠(由.inject(...)完成)的每个步骤中必须包含下一秩和迄今所计算的部分列表一个Tuple。作为最后一步,你提取从Tuple结果列表。但这种转换映射到列表中。

该解决方案更简单,因为它是没有必要作出一个新的集合,如果你修改旧的到位,它保留了地图:

def finalResults = groupedByVotes.sort()
finalResults.inject(1, { acc, entry ->
    entry.value.each { it.ranking = acc }
    return acc + entry.value.size()
})

但是,这两种解决方案都没有真正发挥作用。就好像它们是不可变的真正的功能代码对待所有值。看我为一个真正实用的解决方案的其他答案(即将)。

© www.soinside.com 2019 - 2024. All rights reserved.