![](/img/trans.png)
[英]What's the idiomatic way to split a Smalltalk array at the spot where a series of values changes?
[英]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.