Array of records


#1

I have and array of records that looks like this:

nodes = array()
nodes[index]={“number”:node_number,“last_record”:0,“first_record”:0,“cum_r”:0,“cum_g”:0,“cum_b”:0,“cum_w”:0,“cum_p”:0,“v”:0,“v_ts”:0,“rssi”:0,“status”:0}

to keep track of data on a series of sensor nodes. I run into a problem when I want to add a new node. I can simply do this:

nodes[]={“number”:node_number,“last_record”:0,“first_record”:0,“cum_r”:0,“cum_g”:0,“cum_b”:0,“cum_w”:0,“cum_p”:0,“v”:0,“v_ts”:0,“rssi”:0,“status”:0}

and assign values to the fields. And that works find.

The problem comes in from the fact that the data fields are meant to be dynamic, so that occasionally, I’ll add or delete fields (in all of the array records). But I don’t necessarily track what the most current field configuration is. I thought to simply create a new array element by copying the previous element to give me the current field structure. And then update the fields for the new element to reflect the new data (i.e. below node_number = the new node created ).

		nodes[new_index]=nodes[(new_index-1)]    //create new element and copy previous 
		nodes[new_index].number = node_number //update the number field in the new record

So that part almost works, but not according to plan. When I check back on my records, I find that ALL of the records have taken on the new node number that was supposed to be assigned only to nodes[new_index]. Is there something I’m doing wrong that I’m not seeing?

When I update existing records with new values I use the same technique (i.e.: nodes[index].cum_b = value)
which works just fine.


#2

The code nodes[new_index]=nodes[(new_index-1)] only copies the reference, not the whole object. You need to create an explicit copy of the data. There are a couple of approaches. If the table of data in each array element is only one level deep, you can use clone.
eg nodes[new_index]=clone nodes[(new_index-1)]

If it includes nested tables and arrays you’ll need to use a deep copy routine.
eg nodes[new_index]=deepCopy(nodes[(new_index-1)])

with

function deepCopy(container){
  // container must not have circular references
  switch(typeof(container)){
  case "table":
    local result = clone container
    foreach( k,v in container)
      result[k] = deepCopy(v)
    return result;
  case "array":
    return container.map(deepCopy)
  default:
    return container
  }
}

Another option would be to use the squirrel classes. Rather than using a table to store the data, you could create an instance of a class container that supported all the fields you mention. Electric Imp has some good documentation on how that can be done.


#3

Thanks!

I have a simple one-level table structure. So the clone function works perfectly. I’m sorry, that II was not familiar with the ‘clone’ function. I’m juggling too many languages for my own good. I’ll keep a reference to the deepCopy function which may come in handy at a later point.

I’m an old-time programmer and not used to storing data in classes. Hadn’t even occurred to me. I’ll check that out to see if it might be more efficient.