Как преобразовать строку Ruby со скобками в массив?

Я хотел бы преобразовать следующую строку в массив / вложенный массив:

str = "[[this, is],[a, nested],[array]]"

newarray = # this is what I need help with!

newarray.inspect  # => [['this','is'],['a','nested'],['array']]
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
9
0
9 794
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Похоже на простую задачу синтаксического анализа. Как правило, подход, который вы собираетесь использовать, заключается в создании рекурсивной функции со следующим общим алгоритмом

base case (input doesn't begin with '[') return the input
recursive case:
    split the input on ',' (you will need to find commas only at this level)
    for each sub string call this method again with the sub string
    return array containing the results from this recursive method

Единственная немного сложная часть здесь - это разделение ввода на один ','. Вы можете написать для этого отдельную функцию, которая будет сканировать строку и вести подсчет открытых скобок - закрытых скобок, замеченных до сих пор. Затем разделяйте запятыми только тогда, когда счетчик равен нулю.

Создайте рекурсивную функцию, которая принимает строку и целочисленное смещение и "считывает" массив. То есть он должен вернуть массив или строку (которую он прочитал) и целочисленное смещение, указывающее после массива. Например:

s = "[[this, is],[a, nested],[array]]"

yourFunc(s, 1) # returns ['this', 'is'] and 11.
yourFunc(s, 2) # returns 'this' and 6.

Затем вы можете вызвать его с помощью другой функции, которая обеспечивает смещение 0 и гарантирует, что окончательное смещение равно длине строки.

Для смеха:

 ary = eval("[[this, is],[a, nested],[array]]".gsub(/(\w+?)/, "'\1'") )
 => [["this", "is"], ["a", "nested"], ["array"]]

Отказ от ответственности: вам определенно не следует этого делать, так как eval - ужасная идея, но она быстрая и имеет полезный побочный эффект в виде исключения, если ваши вложенные массивы недействительны.

Ответ принят как подходящий

С YAML вы получите то, что хотите.

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

str = "[[this, is], [a, nested], [array]]"

Код:

require 'yaml'
str = "[[this, is],[a, nested],[array]]"
### transform your string in a valid YAML-String
str.gsub!(/(\,)(\S)/, "\1 \2")
YAML::load(str)
# => [["this", "is"], ["a", "nested"], ["array"]]

Спасибо вам большое за это! Я собирался сойти с ума, пытаясь понять это. :)

CalebHC 03.06.2010 08:59

Вы также можете рассматривать его как почти JSON. Если строки действительно представляют собой только буквы, как в вашем примере, то это будет работать:

JSON.parse(yourarray.gsub(/([a-z]+)/,'""'))

Если бы они могли иметь произвольные символы (кроме [],), вам понадобилось бы немного больше:

JSON.parse("[[this, is],[a, nested],[array]]".gsub(/, /,",").gsub(/([^\[\]\,]+)/,'""'))

Другие вопросы по теме