2014-01-20 3 views
1

У меня есть группировка строковых переменных, которая будет чем-то вроде "height_low". Я хочу использовать что-то чистое, как gsub или что-то еще, чтобы избавиться от подчеркивания и всего прочего. так что это будет как "height". У кого-то есть решение для этого? Благодарю.Манипулировать строку в ruby ​​

+0

Неправильный вопрос. Спасибо за помощь, но я разместил всю соответствующую информацию. Если у вас есть идеи, я был бы рад услышать. –

+0

Да, я понял тебя. Благодарю. Мне просто интересно, почему вы прокомментировали этот вопрос относительно другого. –

ответ

1

Шортер:

my_string.split('_').first 
+0

Все очень хорошие ответы, но ваш получает чек, потому что это версия, которую я использовал. Я на самом деле перебирал хэш и нуждался в преобразовании каждого ключа в строку, а затем обрезал конец каждого. Я использовал x.to_s.split ('_'). Сначала, где x является хэш-ключом для выполнения этого. Спасибо, парни. –

3

Попробуйте это:

strings.map! {|s| s.split('_').first} 
+0

@ lipanski Я предполагаю, что Linuxios увидел «У меня есть группировка строковых переменных», и предположил, что Брент говорил о массиве. – Ajedi32

+0

'' strings'' находится здесь Array of Strings. Важно упомянуть об этом, потому что отдельные строки работают как массивы, но не отвечают на '' map''. – lipanski

+0

@ Ajedi32 да я это видел, и я исправил свой комментарий – lipanski

0

Если вы ищете что-то "как GSUB", почему бы не просто использовать GSUB?

"height_low".gsub(/_.*$/, "") #=> "height" 

На мой взгляд, хотя, это немного чище:

"height_low".split('_').first #=> "height" 

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

"height_low".partition("_").first #=> "height" 
1

неизбежных регулярок ответ. (Предполагая, что strings представляет собой массив строк.)

strings.map! { |s| s[/^.+?(?=_)/] } 
+0

+1 Я также искал решение Regex .. –

1

Попытка, как показано ниже с помощью str[regexp, capture] → new_str or nil:

Если Regexp подается, согласующий часть строки возвращается. Если захват следует за регулярным выражением, которое может быть индексом или именем группы захвата, следует за регулярным выражением, что вместо этого возвращается компонент MatchData.

strings.map { |s| s[/(.*?)_.*$/,1] } 
+1

Остерегайтесь жадности в двигателе регулярных выражений: '' a_b_c '[/(.*)_.*$/, 1] # => «a_b» '. Вы можете исправить это, используя: '' a_b_c '[/(.*?)_.*$/, 1] # => «a» ', но также будет выполняться привязка и упрощение:' a_b_c' [/^(. *?) _ /, 1] # => "a". При написании шаблонов не добавляйте больше, чем необходимо, иначе вы можете заставить двигатель тратить много процессорных средств, потраченных впустую. –

+0

@theTinMan Спасибо за обучение .. –

1

FWIW, решение, основанное на String#split работает плохо, потому что они должны разобрать всю строку и выделить массив. Их производительность ухудшается по мере увеличения количества подчеркиваний. Следующие работает лучше:

string[0, string.index("_") || string.length] 

Benchmark результатов (с числом подчеркиваний в скобках):

     user  system  total  real 
String#split (0) 0.640000 0.000000 0.640000 ( 0.650323) 
String#split (1) 0.760000 0.000000 0.760000 ( 0.759951) 
String#split (9) 2.180000 0.010000 2.190000 ( 2.192356) 
String#index (0) 0.610000 0.000000 0.610000 ( 0.625972) 
String#index (1) 0.580000 0.010000 0.590000 ( 0.589463) 
String#index (9) 0.600000 0.000000 0.600000 ( 0.605253) 

эталоны:

strings = ["x", "x_x", "x_x_x_x_x_x_x_x_x_x"] 

Benchmark.bm(16) do |bm| 
    strings.each do |string| 
     bm.report("String#split (#{string.count("_")})") do 
      1000000.times { string.split("_").first } 
     end 
    end 
    strings.each do |string| 
     bm.report("String#index (#{string.count("_")})") do 
      1000000.times { string[0, string.index("_") || string.length] } 
     end 
    end 
end 
0

Учитесь думать в терминах поисков против замены. Как правило, проще, быстрее и чище искать и извлекать то, что вы хотите, чем искать и разделять то, что вы не хотите.

Рассмотрим это:

'a_b_c'[/^(.*?)_/, 1] # => "a" 

Он ищет только то, что вы хотите, что текст от начала строки до _. Все, что предшествует _, захватывается и возвращается.

Заместители:

'a_b_c'.sub(/_.+$/, '') # => "a" 
'a_b_c'.gsub(/_.+$/, '') # => "a" 

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

Вот небольшой тест, показывающий, как это влияет на вещи:

require 'fruity' 

compare do 
    string_capture { 'a_b_c'[/^(.*?)_/, 1]    } 
    string_sub  { 'a_b_c'.sub(/_.+$/, '')    } 
    string_gsub { 'a_b_c'.gsub(/_.+$/, '')    } 
    look_ahead  { 'a_b_c'[/^.+?(?=_)/]     } 
    string_index { 'a_b_c'[0, s.index("_") || s.length] } 
end 

# >> Running each test 8192 times. Test will take about 1 second. 
# >> string_index is faster than string_capture by 19.999999999999996% ± 10.0% 
# >> string_capture is similar to look_ahead 
# >> look_ahead is faster than string_sub by 70.0% ± 10.0% 
# >> string_sub is faster than string_gsub by 2.9x ± 0.1 

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

Падение к тактике «поиск» на регулярной основе, как «string_capture» и «look_ahead», это то, что они не обрабатывают отсутствующие _, поэтому, если есть вопрос, будет ли ваша строка иметь или не будет, _, тогда используйте метод «string_index», который будет возвращаться к использованию string.length, чтобы захватить всю строку.

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