在Smalltalk中,如何从数组中选择字符串和整数

时间:2015-05-27 19:02:47

标签: string select integer smalltalk pharo

使用Pharo,我有一个集合,例如

array := #('up' '4' 'b').

我希望使用select:创建一个仅包含数字的集合,前提是它们小于20,以及一个特定的字符串 - 在这种情况下,'向上'和' 4'

我试过了:

array select: [:each | (each='up') | (each asInteger < 50)].  

这导致MessageNotUnderstood因为receiver of "<" is nil

我认为我必须创建一个本地变量x:= each asInteger,但是无法解决这个问题。

3 个答案:

答案 0 :(得分:3)

使用select:,您一次只能访问数组的一个元素。从您的代码中我看到您想要同时访问该数组的两个元素。您可以在这种情况下使用pairsDo:。例如,下面的代码在数组中放入所有以字符串'up'开头的数字。

numbers := OrderedCollection new.
#('up' '5' 'b') pairsDo: [ :first :second |
    ((first = 'up') and: [ second asInteger notNil ])
        ifTrue: [ numbers add: second asInteger ] ]

然后,您可以使用select:仅获取小于20的数字:

numbers select: [:each| each < 20].

答案 1 :(得分:3)

您正在获得MessageNotUnderstood,因为您的代码正在尝试测试'b' asIntegernil是否为b,因为< 20不是整数)是< 50(或| array | array := #('up' '4' 'b' '22'). ^array select: [ :each | each = 'up' or: [ each isAllDigits and: [ each asInteger < 20 ] ] ] ;您的文字和代码中有不同的数字)。因此,您需要做的就是在对待它之前测试每个数组项是否为数字。

这应该在Pharo工作区中起作用:

#('up' '4')

检查结果会得到预期的or:

请注意,我要检查每个字符串是否由所有数字&#34;组成,并且只在这种情况下才进行比较。另请注意,我使用的是and:|,只会根据需要评估阻止参数,而&x则会评估双方。

您也可以创建一个局部变量,正如您所说的那样,但它看起来有点笨拙(我不会调用变量| array | array := #('up' '4' 'b' '22'). ^array select: [ :each | each = 'up' or: [ | integerOrNil | integerOrNil := each asInteger. integerOrNil notNil and: [ integerOrNil < 20 ] ] ] ...除非它是一个x坐标):

import UIKit
import Parse

class DashboardViewController: UIViewController {

@IBOutlet var welcomeText: UILabel!


override func viewDidLoad() {
    super.viewDidLoad()


}

override func viewWillAppear(animated: Bool) {

    if  let currentUser = PFUser.currentUser()?.username {

        welcomeText.text = "Welcome  \(currentUser)!"

    } else {

        welcomeText.text = "Welcome"
    }


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

  }
}

答案 2 :(得分:2)

您收到错误,因为始终执行第二个比较语句:消息| pharo(和任何smalltalk)不能作为同音C运算符,而是始终执行,无论语句的第一部分的结果如何(与&amp;,btw相同)。

为了得到类似的结果你似乎假装(只要第一个句子为真,就执行or子句),我们使用消息或:和:

你可以这样做:

array select: [ :each | 
    each = 'up'
    or: [ each = '4' 
    or: [ each isAllDigits and: [ each asInteger < 20 ] ] ] ]

注意用于调用#or:语句的嵌套以及我首先检查该数字是否可以转换为数字的事实。如果我不这样做,当我尝试将字符串转换为数字时,我将得到 nil ,因为将字符串解析(转换)为数字失败(然后选择将失败) )。

另一种可能的方法是:

array select: [ :each | 
    each = 'up'
    or: [ each = '4' 
    or: [ each asInteger notNil and: [ each asInteger < 20 ] ] ] ]

但是我推荐第一个(使用解析器的失败来确定字符串是否包含数字可以很容易地被认为是一种利用:)

最后,如果你必须选择多于一个或两个&#34;常数&#34;字符串,您可以执行以下操作:

constants := #('up' '4').
array select: [ :each | 
    (constants includes: each)
    or: [ each asInteger notNil and: [ each asInteger < 20 ] ] ]

这可能是一个更干净的实现。