簡體   English   中英

在Smalltalk中檢測數組中x次相同對象序列的慣用法?

[英]Idiomatic way to detect sequences of x times same object in an Array in Smalltalk?

在OrderedCollection或Array中檢測相同對象(或具有特定匹配參數的對象)x次序列的慣用方法是什么?

例如,數組是否包含連續數字5的10倍?

我喜歡Uko的答案,並希望提供一個解決問題“匹配參數”部分的不同解決方案。 SequenceableCollection定義:

contains: m consecutiveElementsSatisfying: block
    | n i |
    self isEmpty ifTrue: [^m = 0].
    n := self size - m + 1.
    i := 1.
    [i <= n] whileTrue: [| j |
        (block value: (self at: i)) ifTrue: [
            j := 2.
            [j <= m and: [block value: (self at: i + j - 1)]]
                whileTrue: [j := j + 1].
            j > m ifTrue: [^true]].
        i := i + 1].
    ^false

現在,例如,以下兩個表達式將評估為true

#(2 1 1 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e = 1]
#(2 1 0 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e squared = e]

注意 :如果你想要這個方法的startingAt: n版本,只需在主循環之前初始化i := n而不是i := 1

編輯:

當然,我們可以在SequenceableCollection使用以下方法完成協議:

contains: m consecutiveTimes: anObject
    ^self contains: m consecutiveElementsSatisfying: [:e | e = anObject]

這個例子:

#(2 1 1 1 2) contains: 3 consecutiveTimes: 1

我要說你必須遵循這樣的模式:

(collectionToTest
  indexOfSubCollection: (
    Array
      new:     numberOfRepetitions
      withAll: desiredObject)
    startingAt: 1
) isZero not

也許我不知道Pharo中的一些有用的方法,但如果你定義像:

SequenceableCollection >> indexOfSubCollection: aSubCollection
  ^ aSubCollection indexOfSubCollection: aSubCollection startingAt: 0

SequenceableCollection >> containsSubCollection: aSubCollection
  ^ (aSubCollection indexOfSubCollection: aSubCollection) isZero not

Object >> asArrayOf: aLength
  ^ Array new: aLength withAll: self

那么定義可以扁平化為:

collectionToTest containsSubCollection:
  (desiredObject asArrayOf: numberOfRepetitions)

或者為你的例子:

anArray containsSubCollection: (5 asArrayOf: 10)

PS我不確定方法名稱。 也許inArrayOf:可以比asArrayOf:更好asArrayOf:依此類推。

獲取重復對象的序列非常簡單:

({ 1. 1. 2. 2. 2. 5. 5. 3. 9. 9. 9. 9. } as: RunArray) runs 
=> #(2 3 2 1 4)

如果要測試是否存在滿足特定約束的運行,則可以執行以下操作:

meetsConstraint := false.
({ 1. 1. 2. 2. 2. 5. 5. 3. 9. 9. 9. 9. } as: RunArray) runsAndValuesDo: [:run :value | 
    meetsConstraint := (value = 9 and: [run > 3])].

如果要測試對象的某個屬性而不是對象相等,則可以通過執行collect: on來輕松創建此屬性的RunArray

因此,通用解決方案看起來像這樣:

SequenceableCollection >> containsRunOf: anElement withAtLeast: nElements
    (self as: RunArray) runsAndValuesDo: [:run :value | 
        (value = anElement and: [run >= nElements]) ifTrue: [^ true]].
    ^ false

接着:

({ 'aa'. 'bb'. 'c'. 'ddd'. } collect: [:each | each size])
    containsRunOf: 2 withAtLeast: 3
=> false

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM