在Ruby中动态创建数组

时间:2009-12-01 21:56:33

标签: ruby arrays hash

有没有办法在Ruby中动态创建数组?例如,假设我想循环浏览一系列书籍作为用户的输入:

books = gets.chomp

用户输入:

"The Great Gatsby, Crime and Punishment, Dracula, Fahrenheit 451,
Pride and Prejudice, Sense and Sensibility, Slaughterhouse-Five, 
The Adventures of Huckleberry Finn"

我把它变成一个数组:

books_array = books.split(", ")

现在,对于每本书的用户输入,我想用Ruby创建一个数组。伪代码:

 x = 0

 books_array.count.times do
    x += 1
    puts "Please input weekly sales of #{books_array[x]} separated by a comma."
    weekly_sales = gets.chomp.split(",")
 end

显然这不起作用。它会一遍又一遍地重新定义weekly_sales。有没有办法实现我所追求的目标,并且.times方法的每个循环都会创建一个新数组?

6 个答案:

答案 0 :(得分:7)

weekly_sales = {}
puts 'Please enter a list of books'
book_list = gets.chomp
books = book_list.split(',')

books.each do |book|
  puts "Please input weekly sales of #{book} separated by a comma."
  weekly_sales[book] = gets.chomp.split(',') 
end

在ruby中,有一个哈希的概念,它是一个键/值对。在这种情况下,weekly_sales是哈希,我们使用书名作为键,数组作为值。

我对你的代码做了一个小改动,而不是使用books.count.times来定义循环,然后用计数器取消引用数组元素,每个都是迭代集合的更好方法。

答案 1 :(得分:2)

“push”命令会将项目附加到数组的末尾。

Ruby Docs->Array->push

答案 2 :(得分:1)

您需要一种更强大的数据结构。

你的帖子倾向于认为weekly_sales是一个与books数组平行的数组。这种方法的缺点是你必须自己维护这两个数组的并行性。

一个更好的解决方案是使用书名作为数组哈希的关键,正如几个答案所暗示的那样。例如:weekly_sales['Fahrenheit 451']将包含该图书的销售数据数组。这种方法取决于书籍标题的独特性,还有其他缺点。

您可能需要考虑的更强大的方法是将每本书的信息捆绑在一起。

最简单的一端是哈希列表。每本书都是这样一个独立的单元:

books = [
    {
        'title' => 'Fahrenheit 451',
        'sales' => [1,2,3],
    },
    {
        'title' => 'Slaughterhouse-Five',
        'sales' => [123,456],
    },
]

puts books[1]['title']

另一方面是创建一个合适的Book类。

中间方法是使用Struct(或OpenStruct),它在哈希和完整对象之间占据中间地带。例如:

# Define the attributes that a Book will have.
Book = Struct.new(:title, :weekly_sales)
books = []

# Simulate some user input.
books_raw_input = "Fahrenheit 451,Slaughterhouse-Five\n"
sales_raw_input = ['1,2,3', '44,55,66,77']
books_raw_input.chomp.split(',').each do |t|
    ws = sales_raw_input.shift.split(",")
    # Create a new Book.
    books.push Book.new(t, ws)        
end

# Now each book is a handy bundle of information.
books.each do |b|
    puts b.title
    puts b.weekly_sales.join(', ')
end

答案 3 :(得分:0)

您是否乐意最终获得阵列数组?这可能是有用的:

book_sales = books_array.collect do |book|
  puts "Please input weekly sales of #{books_array[0]} separated by a comma."
  gets.chomp.split(",").collect{ |s| s.to_i }
end

看着它,你可能更喜欢用书键入的哈希。像这样:

book_sales = books_array.inject({}) do |hash, book|
  puts "Please input weekly sales of #{books_array[0]} separated by a comma."
  weekly_sales = gets.chomp.split(",").collect{ |s| s.to_i }
  hash[book] = weekly_sales
end

答案 4 :(得分:0)

此解决方案假定永远不会有重复的书名。我觉得这很安全,是吗?

input = "A list of words"
hash = {}
input.split(/\s+/).collect { |word| hash[word] = [] }

# Now do whatever with each entry
hash.each do |word,ary|
   ary << ...
end

答案 5 :(得分:0)

result = "The Great Gatsby, Crime and Punishment, Dracula, Fahrenheit 451,
  Pride and Prejudice, Sense and Sensibility, Slaughterhouse-Five, 
  The Adventures of Huckleberry Finn".split(/,\s*/).map do |b|
    puts "Please input weekly sales of #{b} separated by a comma."
    gets.chomp.split(',') # .map { |e| e.to_i }
end
p result

如果您希望将输入字符串转换为数字

,请删除注释