集合中

时间:2015-11-17 14:12:24

标签: smalltalk pharo idiomatic

我有一个像

这样的字符串数组
#(#('smalltalk' 'pharo' 'cool')
  #('smalltalk' 'pharo' 'new')
  #('smalltalk' 'cool'))

并且想要计算不同系列中Strings的共同发生量,所以我会得到以下信息:

  

smalltalk,pharo,2
  smalltalk,cool,2
  smalltalk,new,1
  pharo,cool,1
  pharo,new,1
  cool,new,0(0次出现是可选的)

最惯用的使用Smalltalk(Pharo的)收集方法来收集这些数据是什么? (结果可以存储在一些带有element1,element2和count变量的简单对象中。)

我可以提出一些简单的解决方案,但与过去类似的问题一样,我发现,我错过了一个漂亮的Smalltalk解决方案,而是做了一些愚蠢的循环。

2 个答案:

答案 0 :(得分:4)

这也给出了相反的情况,但我很好 它看起来非常清晰,现在的问题是,如果效率很高:

|source bagOfPairs|

source := #(#('smalltalk' 'pharo' 'cool')
  #('smalltalk' 'pharo' 'new')
  #('smalltalk' 'cool')).

bagOfPairs := Bag new.
source do: [ :each | 
    each allPairsDo: [:first :second |
    (first = second) ifFalse: [bagOfPairs add: {first . second}]
    ].
].
bagOfPairs inspect.

答案 1 :(得分:2)

我没有看到任何惯用语,这是一个相对复杂的操作,我会分解成这些操作(原型代码):

countAssociatedPairsIn aCollection
    | set pairs |
    set := aCollection flattenAllElementsInto: Set new.
    pairs := set generateAllPairs.
    ^pairs collect: [:pair | pair -> (aCollection count: [:associations | associations includesAll: pair])]

如果你想按计数排序,那么它只是另一个sortedBy:#value

如果你只是打印而不是收集:,你可以在do:

中打开一些循环

仍然需要实现flattenAllElementsInto :(简单,像扁平的asSet)和generateAllPairs(或某种allPairsDo:如果你只是打印,有SequenceableCollection>> #combinations:atATimeDo:这对于这个任务来说很方便)。

countAssociatedPairsIn aCollection
    | items |
    items:= aCollection flattened asSet asArray sorted.
    items combinations: 2 atATimeDo: [:pair |
        Transcript cr;
            print: pair; nextPutAll: '->';
            print: (aCollection count: [:associations | associations includesAll: pair]);
            flush]