Ruby: получение символа [n] из каждого элемента массива строк, строго с обозначением массива - PullRequest
2 голосов
/ 13 марта 2019

Предположим, у меня есть это:

x = %w(greater yellow bandicooot)

И я хочу получить конкретную букву каждой строки в виде строки. Конечно, я могу сделать что-то вроде этого (чтобы получить первую букву):

x.map { |w| w[0] }.join  # => 'gyb'

Но я хотел бы знать, есть ли способ сделать это, используя только обозначение массива. Я пробовал это:

x[0][0]..x[-1][0]

Который возвращает, в этом случае, не очень полезный "g".."b". Я мог бы также использовать обозначение массива, как это в этом случае:

x[0][0] + x[1][0] + x[2][0]

Но я ищу решение, не зависящее от конкретного случая, которое не требует итерации.

Есть ли способ сделать это строго с помощью нотации массива, или необходимо выполнить какую-то итерацию? И если вы не можете сделать это с помощью записи массива, есть ли лучший способ сделать это, чем использовать map и join?

Ответы [ 3 ]

3 голосов
/ 14 марта 2019

Вот причудливый способ регулярного выражения, если у вас есть слово, объединенное в одну строку, разделенную пробелом:

string = "greater yellow bandicooot"
string.gsub /([^ ])[^ ]* */, '\1'
# => "gyb"

Объяснение регулярного выражения:

  • ([^ ]): группа совпадений - один непробельный символ
  • [^ ]* *: необязательная последовательность непробельных символов, за которой следует любая необязательная последовательность пробелов.

Как вы можете прочитать здесь: Ruby regex - gsub захватывает только группу , при использовании gsub заменяется все в регулярном выражении, независимо от того, находится ли оно в группе совпадений. Поэтому вам нужно использовать специальную переменную \1 в вызове gsub (кстати, она должна быть в единственной строке в кавычках) для ссылки на первую группу совпадений, которую вы хотите использовать в качестве вывода.

2 голосов
/ 24 марта 2019

Я не верю, что есть способ сделать то, что вы хотите, но вы могли бы сделать следующее.

str = %w(greater yellow bandicooot).join(' ')
  #=> "greater yellow bandicooot"

str.gsub(/(?<=\S)./, '')
  #=> "gyb"

Регулярное выражение соответствует любому символу, которому предшествует непробельный символ;то есть он соответствует всем символам, кроме первого символа строки и символов, которым предшествует символ пробела.

Если задана строка и между словами может быть несколько пробелов, можно написать:

str.squeeze(' ').gsub(/(?<=\S)./, '')
2 голосов
/ 14 марта 2019

И если вы не можете сделать это с помощью записи массива, есть ли лучший способ сделать это, чем использовать map и join

Ну, коротко (и неправильно :))ответ «это невозможно» - чтобы получить каждый n-й символ каждой строки в массиве, который вы, очевидно, должны повторять (и да, регулярное выражение тоже итерация - скорее всего, менее производительная, чем итерация массива).

Но давайтепредставьте, что у вас есть настоящее приложение, где вы должны выполнять эту операцию очень часто, а список строк огромен (поэтому итерации болезненны).С другой стороны, список строк редко изменяется, и вам почти никогда не нужно возвращать исходные строки.

В этом случае вы можете заимствовать идею хранения столбцов и преобразовывать исходный массив во что-то вроде

transposed_x = ["gyb", "rea", "eln", "ald", "toi", "ewc", "r_o", "__o", "__o", "__t"]

, где каждый n-й элемент является просто конкатенациейn-й символ каждой исходной строки (здесь я заменяю «отсутствующий» символ на _ для ясности).С помощью этой модели данных вы можете выполнить исходную задачу 1) только с помощью записи массива и 2) в O (1).В качестве очевидного компромисса вам придется выполнять итерации для каждой другой операции (выборка исходной строки, добавление / удаление / обновление и т. Д.) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...