集合中元素的共现

Co-occurrence of elements in collections

我有一个字符串数组,例如

#(#('smalltalk' 'pharo' 'cool')
  #('smalltalk' 'pharo' 'new')
  #('smalltalk' 'cool'))

并且想计算字符串在不同集合中的共现次数,所以我会得到以下信息:

smalltalk, pharo, 2
smalltalk, cool, 2
smalltalk, new, 1
pharo, cool, 1
pharo, new, 1
cool, new, 0 (0 occurences are optional)

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

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

这也给出了相反的情况,但我没问题。
它看起来很清晰,现在的问题是,它是否有效:

|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.

我看不出那么地道,这是一个比较复杂的操作,我会分解成这些操作(原型代码):

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]