Jump to content
iwato

How to Reassign a Subset of Property-Value Pairs of an Array of Objects to a New Array of Objects

Recommended Posts

BACKGROUND:  I have created a function whose job is to recreate an array of objects whose objects contain a vastly reduced, pre-selected number of property-value pairs.  Although my function recreates the desired properties, the values are returned undefined.

THE CODE:

var propertyArr = ['serverDate', 'visitorId', 'visitCount'];
function getEntries (propertyArr, inputArr) {
    var entryArr = [];
    var entry = {};
    $.each(inputArr, function(key, object) {
        for(var property in propertyArr) {
            var prop = propertyArr[property];
            entry[prop] = object.prop;
        } 
        entryArr.push(entry);
    });
    return entryArr;
}
console.log('entryArr', getEntries(propertyArr, jsonData));

THE RESULT SET

entryArr Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 90 more… ]

where a typical object appears as follows:

Object:
	serverDate: undefined
	visitorId: undefined
	visitCount: undefined

QUESTION:  Where have I gone wrong, and what can I do to fix my error.

Roddy

 

 

 

 

Edited by iwato
Code upgrade

Share this post


Link to post
Share on other sites

Almost there, a portion of the problem has been resolved with the following alteration.

entry[prop] = object[prop];

I have just learned that there is a reason for having two ways to call the values of object properties.

Unfortunately, the iteration is not working properly, for every object returns the same key-value pairs -- those of the last object only.  Woe unto me!

Roddy

Edited by iwato

Share this post


Link to post
Share on other sites

The variable entry should be declared inside the .each() callback.

  • Like 1

Share this post


Link to post
Share on other sites

That was it!  Thank you, Ingolme.

Now, if I could only understand it.  There appears to be much more involved in this case than a simple matter of scope.  How is it that I am able to recreate the same variable over and over again?  Roddy

var entry = {}:

Share this post


Link to post
Share on other sites

The problem before is that you created only one object and on each iteration you changed the properties of that object and added a new pointer to it from the array. What you really need to do is to create a new object on each iteration.

You can recreate the variable every time because it is inside its own function.

Another option would be to declare the object outside and initialize it inside the loop:

var entry; // Reserve memory for storing objects
$.each(inputArr, function(key, object) {
  entry = {}; // Create a new instance of an object and place it in the reserved memory
  for(var property in propertyArr) {
    var prop = propertyArr[property];
    entry[prop] = object.prop; // Set the properties of the object
  } 
  entryArr.push(entry); // Add a pointer to the new object at the end of the array
});
return entryArr;

They both do the same thing but for different reasons.

  • Like 1

Share this post


Link to post
Share on other sites

You appear to be saying that each iteration of the same function is a different function.  Have I understood correctly?

Roddy

Share this post


Link to post
Share on other sites

No, it is the same function. Every time the program enters a function, new memory is allocated for it. When the program leaves the function all of the memory used by the function is freed unless there are pointers to it from another part of the program, such as the array that was declared outside.

  • Like 1

Share this post


Link to post
Share on other sites

OK.  I think I have it.  Using your last example as my heuristic template, then

1) Create a space in memory called entry.

var entry;

2) Fill that space with a new object called entry with each iteration of the $.each() function.

entry = {}; // Create a new instance of an object and place it in the reserved memory
for(var property in propertyArr) {
  var prop = propertyArr[property];
  entry[prop] = object.prop; // Set the properties of the object
} 

3) From that storage space retrieve the current value of entry (the just created object) and add it to a predefined array called entryArr.

entryArr.push(entry);

Is this correct?

Roddy

 

Share this post


Link to post
Share on other sites

The last example I wrote is a bit more complicated at the processor level, I was just showing an alternative way to do things. It is probably best to have the declaration inside the each() callback as I said initially.

You're mostly correct, with a couple of differences due to the way scope and references work.

2) If the space does not have an object yet, it behaves as you said and puts the object in that space. If there was already an object in that space, the variable entry is changed to point to a new space in memory and the new object is placed there instead. The old object remains exactly where it was as long as there is a pointer to it from somewhere, like the entryArr array.

3) The value is not retrieved from the storage space, instead the array just contains a reference to that space in memory telling it that the object is there.

This distinction is important, because the error you had initially occurs because all of the array elements had pointers to the same piece of memory meaning that changing one of them would change all of them.

I've attached a short diagram explaining basically how the memory works in this situation. It's not 100% accurate, but it would take at least a semester course to teach the details.

memory.png

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, ingolme, for the excellent presentation. 

As a new object will be added to the current search and recover operation with each new day, the number of objects required to generate the designated graph for which this function was created will soon become very large.  It would appear that the two-step approach that you have outlined in the above diagrams is more efficient than the one-step approach initially suggested.  What do you think?

Roddy

Share this post


Link to post
Share on other sites

Both of them are equally efficient, they reserve the same amount of memory and they take the same amount of processing time. The only difference between them is the context in which the memory is reserved. I would recommend with putting the entry variable inside the each() callback only because you don't need it anymore after the process has ended.

  • Thanks 1

Share this post


Link to post
Share on other sites

The Furtive Fox strikes again!

Thank you for the wonderful elucidation, Ingolme. 

Roddy

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×