2013-11-01 1 views
1

У меня есть отсортированный массив элементов:Возвращаемая подматрица на основе хеш-ключа/диапазона значений?

array = ["A", "B", "C", "D", "E"] 

я определил ряд элементов, где «ключ» является исходным элементом, и «значение» является окончание элемента:

range_1 = {"C" => "D"} 
range_2 = {"B" => "E"} 

Как написать код, возвращающий подмассивы, на основе анализа массивов над массивом?

result_1 = ["C", "D"] 
result_2 = ["B", "C", "D", "E"] 
+3

Если вы хотите выразить диапазоны в Ruby, вы должны использовать '(« C »..« D »)' вместо хэша с одним ключом/значением. Даже хэш с 'start: 'C', end: 'D'' будет лучшим способом представления данных. – meagar

+0

Я только что начал с Ruby, и мне нравится обозначение Hash '=>'. Кажется, мне тоже понравится нотация диапазона. – flyer

+0

@flyer: Если у вас есть единственный инструмент, это молот, каждая проблема выглядит как разбитый большой палец. :) –

ответ

2

Если предположить, что элементы вашего массива являются уникальными:

array = ["A", "B", "C", "D", "E"] 

range_1 = {"C" => "D"} 
range_2 = {"B" => "E"} 

def subarray(array, range) 
    from, to = range.first 
    idx_from = array.index(from) 
    idx_to = array.index(to) 
    array[idx_from..idx_to] 
end 

subarray(array, range_1) # => ["C", "D"] 
subarray(array, range_2) # => ["B", "C", "D", "E"] 
+0

Это хорошо выглядит ... :) –

2
result_1 = array[array.index(range_1.keys.first)..array.index(range_1.values.first)] 
result_2 = array[array.index(range_2.keys.first)..array.index(range_2.values.first)] 
1

Там пахнет, как вы это делаете:

  • Вместо того, чтобы использовать что-то вроде:

    range_1 = {"C" => "D"} 
    range_2 = {"B" => "E"} 
    

    я выбрал бы используя реальные диапазоны:

    range_1 = 'C' .. 'D' 
    range_2 = 'B' .. 'E' 
    

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

    range_1.to_a # => ["C", "D"] 
    range_2.to_a # => ["B", "C", "D", "E"] 
    
    [*range_1] # => ["C", "D"] 
    [*range_2] # => ["B", "C", "D", "E"] 
    
  • Если значения в array не очень последовательно, как в примере, то я бы использовал значение индекса:

    array = ["A", "B", "C", "D", "E"] 
    range_1 = 2 .. 3 
    range_2 = 1 .. 4 
    

    Что делает его легко получить значение:

    array = ["A", "B", "C", "D", "E"] 
    range_1 = 2 .. 3 
    range_2 = 1 .. 4 
    
    array[range_1] # => ["C", "D"] 
    array[range_2] # => ["B", "C", "D", "E"] 
    

Если вам необходимо использовать фактические значения из array в качестве символических имен Fo r индексов становится сложнее, подобно тому, что вы делаете сейчас, но если вы работаете с веб-интерфейсом, это не так уж плохо. Мозг и глаза пользователя - хороший актив.

Поскольку прецедент не определен, мы не можем рекомендовать лучшие решения. Я подозреваю, что это случай, когда вы решили, что какой-то алгоритм является лучшим, и теперь вы пытаетесь заставить его работать, но энтропия настраивается, поскольку вы чувствуете, что угол комнаты закрывается. Это анализ, основанный на много лет смотреть на код, а не на мгновение.


но что-то вроде этого desn't [ "А", "В", "С", "D"] [ "Б" .. "D"]. Я получаю в «[]»: не может преобразовать строку в Integer

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

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

array = %w[a b c d x y z] 
hash = Hash[array.map.with_index{ |e, i| [e, i] }] 
hash # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3, "x"=>4, "y"=>5, "z"=>6} 

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

Это простой пример с использованием одного диапазона:

hash.values_at(*('a' .. 'd')) # => [0, 1, 2, 3] 
hash.values_at(*('x' .. 'z')) # => [4, 5, 6] 

Эти сложные примеры диапазон:

hash.values_at(*('a' .. 'c'), *('x' .. 'z')) # => [0, 1, 2, 4, 5, 6] 
hash.values_at(*('x' .. 'z'), *('a' .. 'c')) # => [4, 5, 6, 0, 1, 2] 

Обратите внимание, что во втором на диапазонах меняются местами, и значения отражают, что ,

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

+0

Спасибо за полезные подсказки. К сожалению, это невозможно использовать, потому что у меня нет последовательных элементов массива, и мне нужно определить «диапазон» по строкам. Рекомендуемые '[" A "," B "," C "] [1..2]' работают отлично, но что-то вроде этого не '[" A "," B "," C "," D "] [ "Б" .. "D"] '. Я получаю 'in '[]': невозможно преобразовать String в Integer' – flyer

+0

Правильно, вы не можете использовать альфа-диапазон, потому что' [] 'поддерживает только целые числа. Ваш массив примеров должен отражать вашу реальность; Если у вас нет последовательных значений в массиве, убедитесь, что это отмечено. Есть очень интересные трюки, которые можно играть с хэш-настройкой и массивом, а хэш-фрагмент не волнует, все ли в порядке. Значения будут получены в том порядке, в котором указаны ключи. –

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