Член массива становится таким же после нажатия моего кода Ruby

В моем коде Ruby длинная шестнадцатеричная строка анализируется и помещается в массив данных (avl_data_array.push(avl_data)). После нажатия, когда я использую puts для отображения массива, все элементы одинаковы...

Код:

data_hex_string = '03D8CAFE01D0000F383630323634303535353134323532081100000180BB016382005B29ED2AEF935C0D00000000000000000C0616004701F0001502C800EF000643273A440000B50012B60010422F2B180000000000000180BACA745E005B29ED2AEF935C0D003000000B0000000C0616004703F0001503C800EF00064326A2440000B5000CB60008422F41180000000000000180BA938536005B29ED2AEF935C0D00270000090000000C0616004703F0001503C800EF0006432705440000B5000CB60008422F19180000000000000180BA5C960E005B29ED2AEF935C0D003200000B0000000C0616004703F0001504C800EF00064328A4440033B5000BB60008422EEC180000000000000180BA1F8371005B29ED2AEF935C0D000000000000000008041600F000C801EF00044326B7440000422F73180000000000000180B9E89182005B29ED2AEF935C0D000000000000000008041600F000C801EF000443268B440000422F30180000000000000180B9B19F93005B29ED2AEF935C0D000000000000000008041600F000C801EF0004432690440000422EED180000000000000180B97AB11B005B29ED2AEF935C0D00000000000000000C0616004703F0001503C801EF0006432672440000B50000B60000422F31180000000000000180B943C385005B29ED2AEF935C0D00000000000000000C0616004703F0001503C801EF0006432681440000B50000B60000422EDA180000000000000180B90CD40F005B29ED2AEF935C0D00000000000000000C0616004703F0001504C801EF0006432681440000B50000B60000422F26180000000000000180B8D5E778005B29ED2AEF935C0D00000000000000000C0616004703F0001504C801EF0006432677440000B50000B60000422F30180000000000000180B89EF589005B29ED2AEF935C0D000000000000000008041600F000C801EF0004432681440000422F30180000000000000180B868034C005B29ED2AEF935C0D00000000000000000C0616004703F0001503C801EF000643267C440000B50000B60000422F0A180000000000000180B83111AB005B29ED2AEF935C0D000000000000000008041600F000C801EF000443267C440000422F3A180000000000000180B7FA1ECA005B29ED2AEF935C0D00000000000000000C0616004704F0001503C801EF0006432681440000B50000B60000422F1D180000000000000180B7C332F5005B29ED2AEF935C0D00000000000000000C0616004704F0001504C801EF0006432686440000B50000B60000422F30180000000000000180B78C431E005B29ED2AEF935C0D000000000000000008041600F000C801EF0004432686440000422F8F180000000011'

avl_data_header = {}
avl_data = {}
avl_data_array = [] 
avl_data_footer = {}

avl_data_header[:packet_len] = data_hex_string[0..3]
avl_data_header[:packet_id] = data_hex_string[4..7]
avl_data_header[:not_usable_byte] = data_hex_string[8..9]
avl_data_header[:avl_packet_id] = data_hex_string[10..11]
avl_data_header[:imei_len] = data_hex_string[12..15]

imei_len_dec = data_hex_string[12..15].to_i(16)
current_add = 16
offset = imei_len_dec * 2
avl_data_header[:imei] = data_hex_string[current_add..(current_add+offset-1)]

current_add = current_add+offset
offset = 2
avl_data_header[:codec_id] = data_hex_string[current_add..(current_add+offset-1)]

current_add = current_add+offset
offset = 2
avl_data_header[:number_data1] = data_hex_string[current_add..(current_add+offset-1)]

data_num = avl_data_header[:number_data1].to_i(16)

for a in 0..(data_num-1) do
  current_add = current_add+offset
  offset = 2 * 8
  avl_data[:timestamp] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2
  avl_data[:priority] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2 * 4
  avl_data[:longitude] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2 * 4
  avl_data[:latitude] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2 * 2
  avl_data[:altitude] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2 * 2
  avl_data[:angle] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2
  avl_data[:satellites] = data_hex_string[current_add..(current_add+offset-1)]

  current_add = current_add+offset
  offset = 2 * 2
  avl_data[:speed] = data_hex_string[current_add..(current_add+offset-1)]
  
  avl_data_array.push(avl_data)
end

current_add = current_add+offset
offset = 2
avl_data_footer[:number_data2] = data_hex_string[current_add..(current_add+offset-1)]

current_add = current_add+offset
offset = 2 * 4
avl_data_footer[:crc_16] = data_hex_string[current_add..(current_add+offset-1)]
    
puts "header: #{avl_data_header}"
puts "data:"
puts avl_data_array
puts "footer: #{avl_data_footer}"

Результат:

header: {:packet_len=>"03D8", :packet_id=>"CAFE", :not_usable_byte=>"01", :avl_packet_id=>"D0", :imei_len=>"000F", :imei=>"383630323634303535353134323532", :codec_id=>"08", :number_data1=>"11"}
data:
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
{:timestamp=>"ED18000000000000", :priority=>"01", :longitude=>"80B97AB1", :latitude=>"1B005B29", :altitude=>"ED2A", :angle=>"EF93", :satellites=>"5C", :speed=>"0D00"}
footer: {:number_data2=>"00", :crc_16=>"00000000"}

Элемент в массиве data должен быть другим. Я новичок в Ruby, но кажется, что грамматик в моем коде правильный. Почему это происходит?

🤔 А знаете ли вы, что...
Ruby имеет богатую стандартную библиотеку, которая упрощает разработку приложений.


36
1

Ответ:

Решено

Why this happens?

Ты никогда не меняешься avl_data. Это всегда один и тот же объект. Следовательно, вы снова и снова подталкиваете один и тот же объект к Array в avl_data_array.

Вот сокращенная версия вашего кода, более четко демонстрирующая проблему:

single_array_element = {}
array = []

3.times do |i|
  single_array_element[:i] = i
  array << single_array_element
end

array.all? {|el| single_array_element.object_id == el.object_id}
#=> true

array
#=> [{ i: 2 }, { i: 2 }, { i: 2 }]

I am Ruby newbie, but it seems the grammer in my code is correct.

Синтаксис действительно правильный, иначе программа даже не запустилась бы — парсер прервался бы с SyntaxError. Но семантика нет: код, который вы написали, на 100% валидный код Ruby, это не ошибка.

Руби делает именно то, что вы ей говорите, вы только что сказали ей сделать что-то не так.