2015-11-23 4 views
1

Вот пример: Это просто упрощенная версия, просто для вас идея, о чем я говорю.Переустановите массивы на основе заданного индекса

current_properties = { "id" : 0, "name":1, "age": 2, "gender":3 } 
new_index = { "id":0, "name":1, "gender": 2, "age": 3, "address":4 } 

А вот значения массива:

arr = ["1234", "John Doe", 35, "Male"] 

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

Так вот ожидаемый выход:

arr = ["1234", "John Doe", "Male", 35, ""] 

ответ

3
current_properties = {"id" => 0, "name" => 1, "age" => 2, "gender" => 3} 
new_index = {"id" => 0, "name" => 1, "gender" => 2, "age" => 3, "address" => 4} 
arr = ["1234", "John Doe", 35, "Male"] 

idx = new_index.map { 
    |key, value| [value, key] 
}.sort.map { 
    |value, key| current_properties[key] 
} 
# => [0, 1, 3, 2, nil] => (A kind of mapping old -> new indexes) 
new_arr = (0...new_index.length).map { |i| idx[i] ? arr[idx[i]] : '' } 
# => ["1234", "John Doe", "Male", 35, ""] 

UPDATE: Сокращенный вариант предложенный @CarySwoveland, используя Enumerable#sort_by:

... 
idx = new_index.sort_by(&:last).map { |key, _| current_properties[key] }   
new_arr = (0...new_index.length).map { |i| idx[i] ? arr[idx[i]] : '' } 
+2

Две небольшие точки: 1. У вас есть 'each.map', где' map' достаточно. Я ожидаю, что вы забыли удалить «каждый» во время редактирования. 2. Вы можете написать 'idx = new_index.map (&: reverse) .sort.map ...' или просто 'idx = new_index.sort_by (&: last) .map {| key, _ | current_properties [ключ]} '. –

+0

@CarySwoveland, Спасибо за комментарий. Я соответствующим образом обновил ответ. – falsetru

2

Предположим, что мы можем добавить по умолчанию в current_properties:

current_properties.default = current_properties.size 
(arr+[""]).values_at *new_index.sort_by(&:last).map {|k,_| current_properties[k]} 
    #=> ["1234", "John Doe", "Male", 35, ""] 

шаги:

После:

current_properties.default = current_properties.size 

для любого значения, которое не является ключевым:

current_properties["hurray!"] 
    #=> 4 

Тогда:

a = arr + [""] 
    #=> => ["1234", "John Doe", 35, "Male", ""] 

b = new_index.sort_by(&:last) 
    #=> [["id", 0], ["name", 1], ["gender", 2], ["age", 3], ["address", 4]] 

c = b.map { |k,_| current_properties[k] } 
    #=> [0, 1, 3, 2, 4] 

a.values_at *c 
    #=> ["1234", "John Doe", "Male", 35, ""] 
1

Раствор с помощью Enumerable API.

def swap_fields(a, old, new) 
    new.size.times.map { |i| old.key?(new.key(i)) ? a[old[new.key(i)]] : '' } 
end 

Или более читаемый.

def swap_fields(a, old, new) 
    new.size.times.map do |i| 
    field_name = new.key(i) 
    current_index = old[field_name] 

    current_index ? a[current_index] : '' 
    end 
end 
+1

Это прекрасно читаемо. Хороший ответ, хотя вы должны заявить о своем предположении, что ключи «new» (aka 'new_index') упорядочены по значению. Обратите внимание, что вы можете упростить 'new.map {| _, i | ... '. –

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