字符串或整个字符串的前 n 个字符;没有下标越界

First n characters of string or whole string; without SubscriptOutOfBounds

在 Pharo 7 中,我试图获取字符串的第一个字符数,或者只是整个字符串(如果请求的字符数超过字符串的长度)。

但是,下面的示例会导致错误,而我只想 return 整个字符串:

    'abcdef' copyFrom: 1 to: 30. "=> SubscriptOutOfBounds Error"
    'abcdef' first: 30. "=> SubscriptOutOfBounds Error"
    'abcdef' first: 3. "=> 'abc'; OK"

是否有一种方法可以在请求的长度超过字符串长度时 return 整个字符串?

作为解决方法,我做了以下操作,首先检查字符串的长度,如果长度超过最大长度,则只发送 first:,但这不是很优雅:

label := aTaskbarItemMorph label size < 30 ifTrue: [ aTaskbarItemMorph label ] ifFalse: [ aTaskbarItemMorph label first: 30 ].

默认情况下,我在 String class 或其超classes 中看不到任何此类方法。您的解决方法是一个很好的解决方案。

或者,更短的解决方法是使用 min: 到 select 字符串的大小或有限的字符数。例如:

string := '123456'.
label := string first: (string size min: 5).

另一种解决方案是向 String class 添加一个扩展方法来执行您想要的操作。因此该方法将添加到 String class 但放在您的包中。例如:

String>>atMost: numberOfElement
    ^ self size < numberOfElement 
        ifTrue: [ self ] 
        ifFalse: [ self first: numberOfElement ]

那么下面的方法就可以了:

string := '123456'.
string atMost: 2.  "'12'"
string atMost: 10. "'123456'"

添加扩展方法时,您可以在它们的名称中添加前缀以避免可能的冲突,例如,如果稍后在 Pharo 中添加方法 atMost:,或者如果另一个包也定义了这样的扩展方法。

这是一个简单的表达式,可以带来你想要的东西:

aString readStream next: n

String>>truncateTo:

'abcdef' truncateTo: 30. "'abcdef'"
'abcdef' truncateTo: 3. "'abc'"

MethodFinder 助您一臂之力

我们还应该记住,对于这种情况,我们在 Pharo 中有 MethodFinder。您可以通过评估您拥有的示例来使用它。在我们的案例中

MethodFinder methodFor: #(('abcdef' 30) 'abcdef' ('abcdef' 3) 'abc')

会产生

"'(data1 contractTo: data2) (data1 truncateTo: data2) '"

其中包含已经提到的 #truncateTo: 并添加 #contractTo:。请注意,后者实现了其他形式的缩短技术,即

'abcdef' contractTo: 6 "'a...f'"

可能不是您今天想要的,而是将来可能有用的信息。


语法

MethodFinder 的语法需要长度为 2 * #examplesArray,其中每个示例都包含一对(输入参数 , 结果).

有趣的是,Squeak 大括号可以轻松提供动态创建的示例:

input := 'abcdef'.
n := 1.
MethodFinder methodFor: {
     {input. input size + n}. input.
     {input. input size - n}. input allButLast
}

也会找到 truncateTo:.