I have thousands of legacy code that stores array information in a non array.
For example:
container.object1 = someobject;
container.object2 = someotherobject;
container.object3 = anotherone;
What I want to have is:
container.objects[1], container.objects[2], container.objects[3] etc.
The 'object' part of the name is constant. The number part is the position it should be in the array.
How do I do this?
Assuming that object1, object2, etc... are sequential (like an array), then you can just iterate through the container object and find all the sequential objectN properties that exist and add them to an array and stop the loop when one is missing.
container.objects = []; // init empty array
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
If you want the first item object1 to be in the [1] spot instead of the more typical [0] spot in the array, then you need to put an empty object into the array's zeroth slot to start with since your example doesn't have an object0 item.
container.objects = [{}]; // init array with first item empty as an empty object
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
An alternate way to do this is by using keys.
var unsorted = objectwithobjects;
var keys = Object.keys(unsorted);
var items = [];
for (var j=0; j < keys.length; j++) {
items[j] = unsorted[keys[j]];
}
You can add an if-statement to check if a key contains 'object' and only add an element to your entry in that case (if 'objectwithobjects' contains other keys you don't want).
That is pretty easy:
var c = { objects: [] };
for (var o in container) {
var n = o.match(/^object(\d+)$/);
if (n) c.objects[n[1]] = container[o];
}
Now c is your new container object, where c.object[1] == container.object1
Related
I had to remove same data in array.
I found this code and its work exactly the way i want but I can not understand part of this code.
please explain this code and WHAT IS THIS >>> a[this[i]] <<<
Array.prototype.unique = function() {
var a = {}; //new Object
for (var i = 0; i < this.length; i++) {
if (typeof a[this[i]] == 'undefined') {
a[this[i]] = 1;
}
}
this.length = 0; //clear the array
for (var i in a) {
this[this.length] = i;
}
return this;
};
Please see the comments before each line that explain that line of code
//added unique function to prototype of array so that all array can have unique //function access
Array.prototype.unique = function() {
//creating a temp object which will hold array values as keys and
//value as "1" to mark that key exists
var a = {}; //new Object
//this points to the array on which you have called unique function so
//if arr = [1,2,3,4] and you call arr.unique() "this" will point to
//arr in below code iterating over each item in array
for (var i = 0; i < this.length; i++) {
//idea is to take the value from array and add that as key in a so
//that next time it is defined. this[i] points to the array item at
//that index(value of i) //and a[this[i]] is adding a property on a
//with name "this[i]" which is the value //at that index so if value
//at that index is lets say 2 then a[this[i]] is //referring to
//a["2"].thus if 2 exists again at next index you do not add it to a
//again as it is defined
if (typeof a[this[i]] == 'undefined') {
a[this[i]] = 1;
}
}
this.length = 0; //clear the array
//now in a the properties are unique array items you are just looping
//over those props and adding it into current array(this) in which
//length will increase every //time you put a value
for (var i in a) {
this[this.length] = i;
}
//at the end returning this which is the modified array
return this;
};
//Edit
stored value of a[this[i]] is 1 for all the keys in a it will be one.
you start with
arr = [1,2,3,2,3,4];
when you call arr.unique
the code in the first loop creates a something like this
a = {
"1":1,
"2":1,
"3":1,
"4":1
}
so you can see that only unique values are as properties in a.
Now in the for-in loop you are just taking the keys of a(ie 1,2,3,4) and adding it to the array(this).
Hope this helps let me know if you need more details
a[this[i]] =>
this[i] -> get i element from current object, in this case it's Array.
a[] -> get element from var a at position specified in [], in this case what value is inside this[i]
How do I get the number of elements in an array with non-consecutive numbers as keys?
var array = [];
array[5] = "something";
array[10] = "nothing":
expected:
number of elements in array = 2
actual:
instead I get the last number used as the "length", 11
I can figure out the way to do this by iterating through each element. Is there is better way to do this?
You may count non empty cells:
array.filter(function(e){return e!==undefined}).length
Sounds like what you actually want is a dictionary, not an array. Have you considered that as an alternative data structure?
How to do associative array/hashing in JavaScript
var myArray = {};
myArray["5"] = "something";
myArray["10"] = "nothing";
And to get the length you would want to write a quick function like the one shown here:
Length of a JavaScript object
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
var size = Object.size(myArray);
Or alternatively, even simpler (but not supported by IE8):
Object.keys(myArray).length
var array = [];
array[5] = "something";
array[10] = "nothing":
Your array in this case becomes :
[undefined,undefined,undefined,undefined,undefined,"something",undefined,undefined,undefined,undefined,"nothing"]
thats why the length is coming as 11. So ideally you should not set it like array[5] or array[10].
If you have variable keys, then you should use object
a = {};
a["5"] = "something";
a["10"] = "nothing"
Then a will look like {"5":"something","10":"nothing"}
Then you can calculate count as :
var elemCount = 0;
for(var key in a){
elemCount++;
}
Output:
elemCount = 2
Various other ways of getting length of keys in object:
How to efficiently count the number of keys/properties of an object in JavaScript?
var array= Array(5);
array[1] = 10;
array[3] = 3;
numberOfElements = 0;
for(var i =0; i<array.length; i++) {
if(array[i]!=undefined)
numberOfElements++;
}
alert(numberOfElements);
I am trying to build an array that should look like this :
[
[{"name":"Mercury","index":0}],
[{"name":"Mercury","index":1},{"name":"Venus","index":1}],
[{"name":"Mercury","index":2},{"name":"Venus","index":2},{"name":"Earth","index":2}],
...
]
Each element is the concatenation of the previous and a new object, and all the indexes get updated to the latest value (e.g. Mercury's index is 0, then 1, etc.).
I have tried to build this array using the following code :
var b = [];
var buffer = [];
var names = ["Mercury","Venus","Earth"]
for (k=0;k<3;k++){
// This array is necessary because with real data there are multiple elements for each k
var a = [{"name":names[k],"index":0}];
buffer = buffer.concat(a);
// This is where the index of all the elements currently in the
// buffer (should) get(s) updated to the current k
for (n=0;n<buffer.length;n++){
buffer[n].index = k;
}
// Add the buffer to the final array
b.push(buffer);
}
console.log(b);
The final array (b) printed out to the console has the right number of objects in each element, but all the indexes everywhere are equal to the last value of k (2).
I don't understand why this is happening, and don't know how to fix it.
This is happening because every object in the inner array is actually the exact same object as the one stored in the previous outer array's entries - you're only storing references to the object, not copies. When you update the index in the object you're updating it everywhere.
To resolve this, you need to create new objects in each inner iteration, or use an object copying function such as ES6's Object.assign, jQuery's $.extend or Underscore's _.clone.
Here's a version that uses the first approach, and also uses two nested .map calls to produce both the inner (variable length) arrays and the outer array:
var names = ["Mercury","Venus","Earth"];
var b = names.map(function(_, index, a) {
return a.slice(0, index + 1).map(function(name) {
return {name: name, index: index};
});
});
or in ES6:
var names = ["Mercury","Venus","Earth"];
var b = names.map((_, index, a) => a.slice(0, index + 1).map(name => ({name, index})));
Try this:
var names = ["Mercury","Venus","Earth"];
var result = [];
for (var i=0; i<names.length; i++){
var _temp = [];
for(var j=0; j<=i; j++){
_temp.push({
name: names[j],
index:i
});
}
result.push(_temp);
}
console.log(result)
try this simple script:
var b = [];
var names = ["Mercury","Venus","Earth"];
for(var pos = 0; pos < names.length; pos++) {
var current = [];
for(var x = 0; x < pos+1; x++) {
current.push({"name": names[x], "index": pos});
}
b.push(current);
}
I'm iterating over array couples and I need to sort one by the order of the other.
Say I have these two arrays:
aLinks = [4,5,6]
bLinks = [1,2,3,4,5,6]
I need to return:
aLinks = [4,5,6]
bLinks = [4,5,6,1,2,3]
meaning that i need to have the items that match first array first and than the rest,
sorted by order if possible.
I'm working with d3 so I'm using forEach to go through the link sets and save the order of aLinks.
I don't know how to apply this order to bLinks
var linkOrder = [];
linkSets.forEach(function(set, i) {
linkOrder = [];
set.aLinks.forEach(function(link,i){
linkOrder.push(link.path);
})
});
You can do it like:
Take out the matching items from second array into a temp array
Sort the temp array
Sort the second array containing only items that did not match
Concatenate the second array into the temp array
Code - With the fix provided by User: basilikum
var first = [4,5,6];
var second = [1,7,3,4,6,5,6];
var temp = [], i = 0, p = -1;
// numerical comparator
function compare(a, b) { return a - b; }
// take out matching items from second array into a temp array
for(i=0; i<first.length; i++) {
while ((p = second.indexOf(first[i])) !== -1) {
temp.push(first[i]);
second.splice(p, 1);
}
}
// sort both arrays
temp.sort(compare);
second.sort(compare);
// concat
temp = temp.concat(second);
console.log(temp);
Working Demo: http://jsfiddle.net/kHhFQ/
You end up with A + sort(A-B) - so you just need to compute the difference between the 2 arrays. Using some underscore convenience methods for example:
var A = [4,5,6];
var B = [1,2,3,4,5,6];
var diff = _.difference(A,B);
var result = _.flattern(A, diff.sort());
iterate the first array, removing the values from the second array and then appending them to the start of the array to get the right order :
var arr1 = [4,5,6];
var arr2 = [1,2,3,4,6,5];
arr1.sort(function(a,b) {return a-b;});
for (i=arr1.length; i--;) {
arr2.splice(arr2.indexOf(arr1[i]), 1);
arr2.unshift( arr1[i] );
}
FIDDLE
suppose I do..
var arr = Array();
var i = 3333;
arr[i] = "something";
if you do a stringify of this array it will return a string with a whole bunch of undefined numeric entries for those entries whose index is less than 3333...
is there a way to make javascript not do this?
I know that I can use an object {} but I would rather not since I want to do array operations such as shift() etc which are not available for objects
If you create an array per the OP, it only has one member with a property name of "333" and a length of 334 because length is always set to be at least one greater than the highest index. e.g.
var a = new Array(1000);
has a length of 1000 and no members,
var a = [];
var a[999] = 'foo';
has a length of 1000 and one member with a property name of "999".
The speedy way to only get defined members is to use for..in:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var p in a) {
if (a.hasOwnProperty(p) && re.test(p)) {
s.push(a[p]);
}
}
return '' + s;
}
Note that the members may be returned out of order. If that is an issue, you can use a for loop instead, but it will be slower for very sparse arrays:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var i=0, iLen=a.length; i<iLen; i++) {
if (a.hasOwnProperty(i)) {
s.push(a[i]);
}
}
return '' + s;
}
In some older browsers, iterating over the array actually created the missing members, but I don't think that's in issue in modern browsers.
Please test the above thoroughly.
The literal representation of an array has to have all the items of the array, otherwise the 3334th item would not end up at index 3333.
You can replace all undefined values in the array with something else that you want to use as empty items:
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == 'undefined') arr[i] = '';
}
Another alternative would be to build your own stringify method, that would create assignments instead of an array literal. I.e. instead of a format like this:
[0,undefined,undefined,undefined,4,undefined,6,7,undefined,9]
your method would create something like:
(function(){
var result = [];
result[0] = 0;
result[4] = 4;
result[6] = 6;
result[7] = 7;
result[9] = 9;
return result;
}())
However, a format like that is of course not compatible with JSON, if that is what you need.