I have two object arrays (which I receive from a server based on some user input):
array1 = [{id:1, name:Bob}, {id:2, name:John}, {id:3, name:Mary}];
array2 = [{id:2, field:true},{id:2, field:true}, {id:3, field:false}];
The id's in both array correspond to each other (they are user ids). In real life these arrays will be much larger (up to 8000 elements in array 1, and 16000 in array2).
The thing I need to accomplish is on the front end I am currently showing just array2 information which displays to the user id and the field. The problem is the front end user doesn't know anyone by their user id instead they know them by their name. I need an array which has objects which look like this: {id:'',name:'',field:''}.
My first thought was to create a new array and "combine the two arrays" :
var new_array = [];
for (var i = 0; i < array2.length; i++) {
var name = 'Unknown';
for (var j = 0; j < array1.length; j++) {
if (array1[j].id === array2[i].id) {
name = array1[j].name;
}
this.new_array.push({
id: array2[i].id,
name: name,
field: array1[j].field
});
}
}
So I loop through the the second array and check if the id matches the id of the first array. If it does I take the name from the first array and that is the user's name so that is how I get the user's name.
This works, but it is kind of slow on the front end, it take a few seconds to do this and if there are many items the user experience doesn't feel good there is a lot of waiting. I am looking for a more efficient way to do what I need to do.
Run through one array and create an object to map id values to entries:
var array2idx = array2.reduce(function(map, value) {
map[value.id] = value;
return map;
}, {});
Now you can find the array2 values with a simple lookup:
var new_array = [];
for (var i = 0; i < array1.length; i++) {
var v2 = array2idx[array1[i].id];
if (v2) {
new_array.push({
id: v2.id,
name: array1[i].name,
field: array1[i].field
});
}
}
That should be considerably faster. Looking up an id in the index object will take almost no time at all.
Related
I have an JavaScript array:
var arr = [["A",["05",90]],["A",["04",240]],["A",["03",235]],["B",["00",123]],["B",["01",234]]];
I want final array to look like:
var final = [["A",[["05",90],["04",240],["03",235]]],["B",[["00",123],["01",234]]]];
The final array is formed by combining all the 2nd element of 2 dimensional array when the 1st element matches.
Please advice how can this be achieved in JavaScript
Object keys are generally the easiest way to create groups like this
var tmp = {}; // temporary grouping object
// loop over data
arr.forEach(function (item) {
// check if group started
if (!tmp.hasOwnProperty(item[0])) {
tmp[item[0]] = [];
}
// push data to group
tmp[item[0]].push(item[1]);
});
// map temp object to results array
var results = Object.keys(tmp).map(function (key) {
return [key, tmp[key]];
});
DEMO
If you start with the array you gave:
var arr = [["A",["05",90]],["A",["04",240]],["A",["03",235]],["B",["00",123]],["B",["01",234]]];
then create a new array to store the values:
var final = [];
and simply combine all of the third-level elements (such as ["05",90] and ["01",234]) of each second-level ones (such as "A" and "B") by looping through the array:
for(var i = 0; i < arr.length; i++) {
var found = false;
for(var j = 0; j < final.length; j++) {
if(arr[i][0] == final[j][0]) {
final[j][1].push(arr[i][1]);
found = true;
break;
}
}
if(!found) {
final[final.length] = [arr[i][0], [[arr[i][1][0], arr[i][1][1]]]];
}
}
This is essentially a sorting method: if the "key" is equal to one in the final array, then it adds it to that one. If not, then appends it to the end of final.
Here's the working example on JSFiddle: link.
This outputs the array:
["A", [["05", 90], ["04", 240], ["03", 235]]], ["B", [["00", 123], ["01", 234]]]
as requested.
Also, as #PaulS commented, it would be recommended to use Objects instead as Strings, to make them Key-Value pairs. But in my answer I stuck with arrays.
I want sort values by array Another
for example
var objName = [{id:1, name:"one"},{id:2, name:"two"}, {id:3, name:"three"}];
var sortById = [1,3,2];
I want this output in that order
1 one
3 three
2 two
Stuff objName elements into a hash (i.e. object) indexed by id, then map the sortById array onto the hash values.
Exact code left as an exercise for the reader.
sorted=new Array()
for(var id_index=0;id_index<sortById.length;id_index++)
{
for(var obj_index=0;obj_index<objName.length;obj_index++){
if (objName[obj_index].id===sortById[id_index]) sorted.push(objName[obj_index])
}
}
//now sorted is the new sorted array. if you want to overwrite the original object:
objName=sorted;
Supposing that the length of both arrays are the same you can first create a hash:
var objName = [{id:1, name:"one"},{id:2, name:"two"}, {id:3, name:"three"}];
var myHash = {};
for(var i = 0; i<objName.length;i++){
myHash[objName[i].id] = objName[i];
}
Once you have this hash, you can loop over your keys array and get the values out:
var sortById = [1,3,2];
var sortedArray = [];
for(var i = 0; i<sortById.length;i++){
sortedArray.push(myHash[sortById[i]]);
}
Something clear and readable (subjective, probably not for everyone):
var result = [];
sortById.forEach(function(id) {
result = result.concat(objName.filter(function(i) {
return i.id == id;
}));
});
JSFiddle: http://jsfiddle.net/RLH6F/
Implemented just for fun.
Warning: O(n^2)
PS: I agree it would be better just give the recipe without the code, but as soon as there are already community members provided the copy-paste solutionы I decided to provide at least a nice looking one.
I have an array that looks like this:
var locationsArray = [['title1','description1','12'],['title2','description2','7'],['title3','description3','57']];
I can't figure out what type of array this is. More importantly, I'm gonna have to create one based on the info there. So, if the number on the end is greater than 10 then create a brand new array in the same exact style, but only with the title and description.
var newArray = [];
// just a guess
if(locationsArray[0,2]>10){
//add to my newArray like this : ['title1','description1'],['title3','description3']
?
}
How can I do it?
Try like below,
var newArray = [];
for (var i = 0; i < locationsArray.length; i++) {
if (parseInt(locationsArray[i][2], 10) > 10) {
newArray.push([locationsArray[i][0], locationsArray[i][1]]);
}
}
DEMO: http://jsfiddle.net/cT6NV/
It's an array of arrays, also known as a 2-dimensional array. Each index contains its own array that has its own set of indexes.
For instance, if I retrieve locationsArray[0] I get ['title1','description1','12']. If I needed to get the title from the first array, I can access it by locationsArray[0][0] to get 'title1'.
Completing your example:
var newArray = [];
// just a guess
if(locationsArray[0][2]>10){
newArray.push( [ locationsArray[0][0], locationsArray[0][1] ] );
}
throw that in a loop and you're good to go.
It's an array of arrays of strings.
Each time there is this : [], it defines an array, and the content can be anything (such as another array, in your case).
So, if we take the following example :
var myArray = ["string", "string2", ["string3-1", "string3-2"]];
The values would be as such :
myArray[0] == "string"
myArray[1] == "string2"
myArray[2][0] == "string3-1"
myArray[2][1] == "string3-2"
There can be as many levels of depth as your RAM can handle.
locationsArray is an array of arrays. The first [] operator indexes into the main array (e.g. locationsArray[0] = ['title1','description1','12']) while a second [] operation indexes into the array that the first index pointed to (e.g. locationsArray[0][1] = 'description1').
Your newArray looks like it needs to be the same thing.
It's an array of array.
var newArray = [];
var locationsArray = [
['title1','description1','12'],
['title2','description2','7'],
['title3','description3','57']
];
for(i = 0; i < locationsArray.length; i++) {
if (locationsArray[i][2] > 10) {
newArray .push([locationsArray[i][0], locationsArray[i][1]]);
}
}
console.log(newArray );
am trying to loop and get the values of names from this array , but am not able..really frustrated with javascript
can anyone please help and guide me to do this and for more complex arrays.. i cant seem to find and tutorial good to show examples of this
thank you , here is the code
var object={name:'angelos',name:'nick',name:'maria'};
var i;
for (i = 0; i < object.length; i += 1) {
document.writeln(object[name][i]);
}
That's an object, not an array. You can make it a simple array instead:
var arr = ['angelos', 'nick', 'maria'];
for (var i = 0; i < arr.length; i++) {
document.writeln(arr[i]);
}
Or, if you want to have objects inside the array (not needed if every object has just one key):
var arr = [{name: 'angelos'}, {name: 'nick'}, {name: 'maria'}];
for (var i = 0; i < arr.length; i++) {
document.writeln(arr[i].name);
}
First of all, your object has duplicate keys name. This is poor code and will throw an error in strict mode.
I would also use either a for ... in loop or Array.forEach here, because much less code is required to implement the desired effect.
Seems like you need to use an Array:
var arr = ["nick", "maria", "chaz"];
arr.forEach(function (name) {
document.writeln(name);
});
You can use Array.forEach, which passes in each index to an anonymous function.
Alternatively, if you wanted each person to be an Object:
var people = [{name: 'chaz', title: 'mr'}, {name: 'nick', title: 'mr'}, {name: 'maria',title: 'ms'}];
for (i in people) {
if (!people.hasOwnProperty(i)) { continue; }
var person = people[i];
document.writeln(person.name);
}
References
Take a look at Array.forEach here
A good reference on for ... in loops here
You can put your data in an array and fill it with objects containing a name attribute (and others e.g. adress or so, if you like to)
http://jsfiddle.net/5NK6x/
var obj=[{name:'angelos'}, {name:'nick'}, {name:'maria'}],
i;
for (i = 0; i < obj.length; i += 1) {
document.write(' ' + obj[i]['name']);
}
First of all, that is an object, not an array. You probably meant to have an array of objects. I'm saying that because you have three keys all called name. Keys must be unique. like this:
var people = [{name: 'angelos'}, {name:'nick'}, {name:'maria'}];
In that case you would loop through like this:
for (var i = 0; i < people.length; i++) {
document.writeln(people[i].name);
}
Example: http://jsfiddle.net/lbstr/cMqaH/
This is a mix between an array and JSON. If your data looked like this:
var object = [{"name":"angelos"},{"name":"nick"},{"name":"maria"}];
You'd be able to access the elements like so:
for(var i=0,i<object.length,i++)
{
alert(object[i].name);
}
I have 2 arrays of objects. Each object has an Id property. Now, if I have a 3rd array of just Ids, what is the better and faster way of finding objects from array1 based on those Ids and moving them to array2.
Thanks a lot for answering..
Sample code:
Person = function(id, fn, ln) {
this.id = id,
this.firstName = fn,
this.lastName = ln
}
array1 = new Array();
// add 500 new Person objects to this array
array2 = new Array();
// add some other new Person objects to this array
function moveArrayItems(ids) {
// ids is an array of ids e.g. [1,2,3,4,5,6,...]
// Now I want to find all the person objects from array1 whose ids
// match with the ids array passed into this method. Then move them to array2.
// What is the best way to achive this?
}
If you really have 500+ objects in each array, you're probably better off using a hash to store the objects, keyed by id:
var people = {
1: {id:1, name:"George Washington"},
2: {id:2, name:"John Adams"},
3: {id:3, name:"Thomas Jefferson"}, // ...
}
var people2 = {}
Now it's trivial (and much, much faster) to move things around by ID:
function moveArrayItems(ids) {
var i,id;
for (i=0; i<ids.length; i++){
id = ids[i];
if (people1[id]) {
people2[id] = people1[id];
delete people1[id];
}
}
}
Good question. It actually made me go back and refer the fundamentals. The key thing about a JS array is that its sparse. You can create an array and assign values for any index (eg: 10 and 23). Based on this fact
array1 = new Array();
array1[person1.id] = person1;
array1[person2.id] = person2;
.... goes till N
function moveArrayItems(ids) {
for(index in ids) {
array2.push(array1[ids[index]]);
delete array1[ids[index]];
}
}
NOTE: I am assuming that Person.id is an integer and less than 2^32 - 1. Refer JS documentation if id is greater or a floating point number. The JS Array implementation is not a contiguous block, so don't think assigning a value to index 12345 requires 12345 continuous blocks of memory.
Just some quick untested pseudo code. This gives a O(n^2) algorithm so it may not be best.
function moveArrayItems(ids) {
// ids is an array of ids e.g. [1,2,3,4,5,6,...]
//Now I want to find all the person objects from array1 whose ids match with the ids array passed into this method. Then move them to array2.
//What is the best way to achive this?
for(i = 0;i < ids.length;i++){
var found = false;
var j = 0;
while(!found && j < array1.length){
if(array1[j].id = ids[i]){
array2.push(array1[j]);
found = true;
}
j++;
}
}
}
First a little function by John Resig
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
Then, merging Vincent's solution
function moveArrayItems(ids)
{
// ids is an array of ids e.g. [1,2,3,4,5,6,...]
// Now I want to find all the person objects from array1
// whose ids match with the ids array passed into
// this method. Then move them to array2.
// What is the best way to achive this?
for(i = 0; i < ids.length; i++)
{
var found = false;
var j = 0;
while(!found && j < array1.length)
{
if(array1[j].id = ids[i])
{
array2.push(array1[j]);
array1.remove(i);
found = true;
}
j++;
}
}
}