Манипулирование строками и массивами в Ruby

#ruby #arrays #string

#ruby #массивы #строка

Вопрос:

У меня есть:

 @fruit = ["Apples, Oranges, Bananas", "Apples", "Bananas, Pears", "Bananas, Apples, Pears", "Pears"]
  

Я хочу сделать с этим две разные вещи, сначала превратив его в чистый массив только с одним экземпляром каждого:

 ["Apples", "Oranges", "Bananas", "Pears"]
  

Во-вторых, я хочу иметь возможность определять, сколько экземпляров данного экземпляра имеется в массиве:

 @fruit.count("Apples") = 3
  

В-третьих, возможно ли упорядочить массив по количеству экземпляров:

 @fruit.sort = ["Apples", "Apples", "Apples", "Bananas", "Bananas", "Bananas", "Pears", "Pears", "Pears", "Oranges"]
  

Какие функции массива / строки я должен был бы использовать для этого?

Ответ №1:

 arr = ["Apples, Oranges, Bananas", "Apples", "Bananas, Pears", "Bananas, Apples, Pears", "Pears"]

hsh = Hash.new { |h, k| h[k] = 0 }

arr.each do |str|
  fruits = str.split(/, /)
  fruits.each do |fruit|
    hsh[fruit]  = 1
  end
end

p hsh.keys
# => ["Apples", "Oranges", "Bananas", "Pears"]

hsh.keys.each { |fruit| puts "#{fruit}: #{hsh[fruit]}" }
# => Apples: 3
# => Oranges: 1
# => Bananas: 3
# => Pears: 3
  

Комментарии:

1. во-первых, это показывает отличную и недостаточно используемую функцию Hash.new -> 1 . и, во-вторых, это экономит вам несколько циклов. помните, что каждый метод перечислителя: map , flatten , uniq и count все они выполняют не менее 1 итерации по вашему массиву.

2. @marian: не беспокойтесь о производительности слишком рано. Функциональные конструкции (map / select / flatten) способствуют хорошему коду, в то время как циклы, использующие пользовательские императивные eachs, сложнее понять.

Ответ №2:

 @fruit = ["Apples, Oranges, Bananas", "Apples", "Bananas, Pears", "Bananas, Apples, Pears", "Pears"]

@fruits = @fruit.map{|f| f.split(", ")}.flatten
#=>["Apples", "Oranges", "Bananas", "Apples", "Bananas", "Pears", "Bananas", "Apples", "Pears", "Pears"]
@fruits.uniq
#=> ["Apples", "Oranges", "Bananas", "Pears"]
@fruits.count{|f| f=="Apples"}
#=>3
  

Комментарии:

1. отлично! Сглаживание, вот чего я не знал! Спасибо.

Ответ №3:

Хэш — лучшая структура данных для этого:

 @fruit = ["Apples, Oranges, Bananas", "Apples", "Bananas, Pears", "Bananas, Apples, Pears", "Pears"]

h = Hash.new

@fruit.each do |str|
  str.split(/,/).each do |f|
    f.strip!
    h[f] ||= 0
    h[f]  = 1
  end
end


h.keys
 => ["Apples", "Oranges", "Bananas", "Pears"] 

h
 => {"Apples"=>3, "Oranges"=>1, "Bananas"=>3, "Pears"=>3} 

h["Apples"]
 => 3
  

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

Ответ №4:

 @fruit = ["Apples, Oranges, Bananas", "Apples", "Bananas, Pears", "Bananas, Apples, Pears", "Pears"]

p @fruit.map{|f| f.split(', ') }.flatten.uniq
#=> ["Apples", "Oranges", "Bananas", "Pears"]

p @fruit.count{|f| f.include?("Apples")}
#=> 3