2014-12-07 2 views
2

Я пытаюсь извлечь подстроку из строки, которая будет подстрока в 2 между разделителями т.е. она должна быть определена следующим образом:извлечь подстроку из строки в Smalltalk (писк)

substring: aString delimiter: aDelimiter 

и, например, если я получу эту строку:

substring: 'dddd#sss#dddd' delimiter: '#' 

Функция должна возвращать 'sss'.

это то, что я пытался, которые не работают:

substring: aString delimiter: aDelimiter 
|index temp1 temp2 sz arr str| 
     arr := aString asArray. 
     sz := arr size. 
     index := arr lastIndexOf: aDelimiter. 
     temp1 := arr first: (sz - index +1). 
     index := temp1 lastIndexOf: aDelimiter. 
     sz :=temp1 size. 
     temp2 := temp1 first: (sz - index). 
     str := temp2 asString. 
     ^str. 

Я не знаю, стоит ли это упоминать, но он должен быть метод класса.

+0

Что делает ваш код? Почему это не работает? –

ответ

3

Ваша основная проблема в том, что аргумент aDelimiter является строкой вместо символа. Вы хотите называть его $ # вместо '#'.

Теперь для более простых способов. Вероятно, проще всего использовать подстроки: метод:

('dddd#sss#dddd' subStrings: '#') at: 2 

Это имеет тот недостаток, что он извлекает всю строку на подстроки, разделенных символом #, который может быть больше, чем нужно.

Следующий простой вариант заключается в использовании потоков:

'dddd#sss#dddd' readStream upTo: $#; upTo: $# 

Этот код только извлекает часть, что вам нужно.

3

Вы находитесь недалеко от рабочего кода, как указал Дэвид. Но я хотел бы отметить, что это очень процедурно. Многие магии Smalltalk и OOP в целом пишут красивый, понятный код, который отправляет намерение раскрывать сообщения сообществу соответствующих объектов. Это включает в себя опираясь на объекты, уже существующие на изображении. Я не могу думать о времени, когда мне пришлось идти на этот низкий уровень для простой задачи, подобной этой. Было бы замечательно прочитать одну из многих удивительных ссылок ООП. Я любимый A Mentoring Course on Smallalk

Я думаю, что решение Давида прямо на. Мне лично нравится second вместо at: 2, но он чувствует себя разборчив и может быть личными предпочтениями ('dddd#sss#dddd' subStrings: '#') second

+0

Мне нравится '' 'second'''. Это яснее, чем '' 'at: 2'''. Это не во всех диалектах Smalltalk, но их легко добавить. –

1

Хотя мне нравится оба из ответов выше, вы можете также рассмотреть вопрос о другом, которая ближе к первой попытке и немного более эффективным, чем другие в том, что он только создает объект, который вы ищете (например, нет промежуточного потока)

substringOf: aString delimitedBy: aCharacter 
    | i j | 
    i := aString indexOf: aCharacter. 
    j := aString indexOf: aCharacter startingAt: i + 1. 
    ^aString copyFrom: i + 1 to: j - 1 

(Обратите внимание, что кстати я также предлагаю немного другой селектор.)

других аспект, который вы хотели бы рассмотреть, - это метод должен реагировать, если aCharacter не находится в aString, он только один раз или имеет три или более случаев. Что-то в линиях:

substringOf: aString delimitedBy: aCharacter 
    | i j | 
    i := aString indexOf: aCharacter. 
    i = 0 ifTrue: [^'']. 
    j := aString indexOf: aCharacter startingAt: i + 1. 
    j = 0 ifTrue: [^'']. 
    ^aString copyFrom: i + 1 to: j - 1 

Но опять же, если производительность не является проблемой в вашем случае, а затем перейти к ответу ReadStream UPTO UPTO, так как это, вероятно, лучше всего.

Смежные вопросы