Ruby Итерация по двумерным массивам и заполнение случайными данными - PullRequest
0 голосов
/ 09 марта 2019

Мне нужно сгенерировать двумерный массив динамического размера с предварительно определенным значением в первом индексе каждого подмассива, тремя случайными значениями в каждом из трех следующих индексов (каждый из которых попадает в другой диапазон) и, наконец, вычисляемым итогом. из трех случайных индексов. Вот что у меня есть.

Пример кода

print("Please enter the number of athletes competing in the triathalon: ")
field=gets.to_i

    count=1
    athlete = Array.new(5)
    triathalon = Array.new(field){athlete}
    triathalon.each do
            athlete.each do
                    athlete.insert(0,count)
                    athlete.insert(1,rand(30..89))
                    athlete.insert(2,rand(90..119))
                    athlete.insert(3,rand(120..360))
            #calculate total time per athlete
                    athlete.insert(4,athlete[1]+athlete[2]+athlete[3])
                    count+=1
            end
    end

1 Ответ

1 голос
/ 09 марта 2019

Один из возможных вариантов - использование Range и отображение диапазона с использованием Enumerable # map .

Например, данные n = 3 спортсменов, базовый пример:

(1..n).map { |n| [n] } #=> [[1], [2], [3]]

Итак, добавив некоторые ваши спецификации в базовый пример:

n = 3
res = (1..n).map do |n|
    r1 = rand(30..89)
    r2 = rand(90..119)
    r3 = rand(120..360)
    score = r1 + r2 + r3
    [n, r1, r2, r3, score]
end

#=> [[1, 38, 93, 318, 449], [2, 64, 93, 259, 416], [3, 83, 93, 343, 519]]


Альтернативный способ добавления суммы элементов в массив - использование Object # tap:
[5,10,15].tap{ |a| a << a.sum } #=> [5, 10, 15, 30]

Таким образом, вы можете написать:

[rand(30..89), rand(90..119), rand(120..360)].tap{ |a| a << a.sum }

Это позволяет записать один вкладыш (используя Array # unshift ):

(1..n).map { |n| [rand(30..89), rand(90..119), rand(120..360)].tap{ |a| a << a.sum }.unshift n }


Исправление вашего кода

Визуализация установки:

field = 3 # no user input for example
p athlete = Array.new(5) #=> [nil, nil, nil, nil, nil]
p triathalon = Array.new(field){athlete.dup} #=> [[nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil]]

ПРИМЕЧАНИЕ athlete.dup, чтобы избежать ссылкик тому же объекту.

Как только вы видите ваши объекты (athlete и triathalon), вы можете понять, что не требуется перебирать вложенный массив, просто доступ по индексу:

count=1
triathalon.each do |athlete|
    athlete[0] = count
    athlete[1] = rand(30..89)
    athlete[2] = rand(90..119)
    athlete[3] = rand(120..360)
    athlete[4] = athlete[1] + athlete[2] + athlete[3]
    count+=1
end

Улучшение: чтобы избавиться от счетчика используйте Enumerable # each_with_index .

...