Разбор очень специфической струнной структуры в ruby ​​(данные бейсбола) - PullRequest
2 голосов
/ 14 февраля 2012

Я пытаюсь написать небольшую программу по статистике бейсбола, используя данные с сайта retrosheet.org, но у меня возникают проблемы с анализом их данных о результатах.В игре, где команда не набирает двузначных чисел в каком-либо конкретном иннинге, их счет будет выглядеть следующим образом 001003000 (они выиграли 1 заезд в третьем иннинге и 3 заезда в шестом).Однако, если команда набирает двойные цифры, данные будут выглядеть следующим образом 00100(10)000 (1 - третий, а 10 - шестой).

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

scores = %w{00100300800 32004300X 00(11)34000 0000(15)000X 0000(15)000(13) 10(18)47(11)8(10)3}

scores.each do |s|
  game = []
  if s.include? "("
    # HELP!
  else 
    s.each_char { |c| game << c }
  end
  puts game.join("+")
end

Я уверен, что решение включает в себя регулярные выражения, в которых я ужасен, поэтому я пробовал все виды ужасных методов манипуляции со строками.В конце концов, я думаю, что будет лучше просто попросить о помощи.

Итак, как бы вы, ребята, сделали это?

Ответы [ 4 ]

5 голосов
/ 14 февраля 2012

Вы можете проанализировать их с помощью scan:

s.scan(/\(\d+\)|\d/)

Например:

>> scores = %w{00100300800 32004300X 00(11)34000 0000(15)000X 0000(15)000(13) 10(18)47(11)8(10)3}
>> scores.each { |s| puts s.scan(/\(\d+\)|\d/).inspect }
["0", "0", "1", "0", "0", "3", "0", "0", "8", "0", "0"]
["3", "2", "0", "0", "4", "3", "0", "0"]
["0", "0", "(11)", "3", "4", "0", "0", "0"]
["0", "0", "0", "0", "(15)", "0", "0", "0"]
["0", "0", "0", "0", "(15)", "0", "0", "0", "(13)"]
["1", "0", "(18)", "4", "7", "(11)", "8", "(10)", "3"]

А затем просто удалите скобки и вызовите to_i:

s.scan(/\(\d+\)|\d/).map { |s| s[/\d+/].to_i }

Например:

>> scores.each { |s| puts s.scan(/\(\d+\)|\d/).map { |s| s[/\d+/].to_i }.inspect }
[0, 0, 1, 0, 0, 3, 0, 0, 8, 0, 0]
[3, 2, 0, 0, 4, 3, 0, 0]
[0, 0, 11, 3, 4, 0, 0, 0]
[0, 0, 0, 0, 15, 0, 0, 0]
[0, 0, 0, 0, 15, 0, 0, 0, 13]
[1, 0, 18, 4, 7, 11, 8, 10, 3]
2 голосов
/ 14 февраля 2012

Вы можете сделать что-то вроде этого:

str = '00(11)34000'
str.scan(/\d{1}|\(\d{2}\)/).map { |a| a.gsub(/[()]/, '') }
# => ["0", "0", "11", "3", "4", "0", "0", "0"]

Здесь я получаю массив типа ["0", "0", "(11)", "3", "4", "0", "0", "0"] и удаляю все ( и ). Здесь я не использую сложные регулярные выражения - вместо этого будет трудно читать.

1 голос
/ 14 февраля 2012

Flipflopping:

str = "0000(15)000X"
tmp = ""
res = []
str.each_char do |c|
  if c=='(' .. c==')' #flip-flop, read like "If we are between '('and ')'.
    tmp << c
  else
   unless tmp.empty?
     res << tmp[1..-2] 
     tmp = ""
   end 
   res << c
  end
end
p res #=>["0", "0", "0", "0", "15", "0", "0", "0", "X"]
1 голос
/ 14 февраля 2012

Вот очень маленький парсер, который выполняет то, что вам нужно:

scores = %w{00100300800 32004300X 00(11)34000 0000(15)000X 0000(15)000(13) 10(18)47(11)8(10)3}
games = []

scores.each do |s|

  game = []
  cs = s.split('')

  cs.each_with_index do |c,i| 
    if cs[i-2] == '('
      game[-1] += c
    elsif !(c == '(' || c == ')')
      game << c
    end
  end

  games << game

end

Обратите внимание, что медленнее , чем при использовании регулярного выражения.

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