Related
I'm trying to figure out an efficient method to sort a multidimensional array based on how many values of another array exist.
Given the following array:
[1,2,3,4,5,6,7,8,9,10]
I am trying to sort another array of arrays based on how many of those values are included.
[
[1,3,5,7,9,22],
[1,200,300,400,500,600],
[1,2,3,4,5,6]
]
So the code I'm trying to get to would return:
[
[1,2,3,4,5,6],
[1,3,5,7,9,22],
[1,200,300,400,500,600]
]
I think what I'm doing is very inefficient and could be written better or more succinctly with a method I'm not aware of?
https://jsfiddle.net/gb3fsLdv/
const compareNums = [1,2,3,4,5,6,7,8,9,10];
let ourData = [
[1,2,3,100,200,300],
[100,200,300,400,500,600],
[1,2,3,5,6,9]
];
function sortArr(compare, data){
let indexMatches = [];
data.map(arr => {
let count = 0;
compare.map(num => {
if(arr.includes(num)){
count++
}
})
indexMatches.push(count);
})
// So now I have indexMatches with a count of how many hits each array has in the correct index order as the original data
// And I can use data to sort them based on these values...
// Little stuck how to relate the two so the same sorting happens to both arrays
}
sortArr(compareNums, ourData);
First convert the given array to set. And then use filter() to get the count of elements included in other array
const data = [
[1,3,5,7,9,22],
[1,200,300,400,500,600],
[1,2,3,4,5,6]
]
let arr = [1,2,3,4,5,6,7,8,9,10];
function getCount(arr, set){
return arr.filter(x => set.has(x)).length
}
function sortOnCount(data, arr){
let set = new Set(arr);
return data.slice(0).sort((a, b) => getCount(b, set) - getCount(a, set))
}
console.log(sortOnCount(data, arr))
I have an array of objects containing objects with similar structure. I need to add a new key value pair to all the objects in the array. How can I do it without looping the entire array.
Providing an example of the output that I require,
let arr = [{a:1,b:2}, {a:2,b:3}];
let key = c;
let value = 3;
Required output will be like,
//arr2 = [ {a:1,b:2,c:3}, {a:2,b:3,c:3}]
P.S: Tried using spread operator with little or no success.
How can I do it without looping the entire array.
You can't (reasonably). The completely unreasonable way would be to add it to Object.prototype, which is inherited by all objects, and thus would add it to all objects in the array — and everywhere else.
But again: You can't reasonably, you need to loop (in one form or another). That loop might be recursion a'la functional programming, but it's basically still a loop.
Here's the recursive technically-not-a-loop way:
let arr = [{a:1,b:2}, {a:2,b:3}];
let el = {c:3};
(function go(a, i, e) {
if (i < a.length) {
a[i].c = e.c;
go(a, i + 1, e);
}
})(arr, 0, el);
console.log(arr);
.as-console-wrapper {
max-height: 100% !important;
}
you can use map() operator on array and Object.assign() to append the key, value pair
let arr = [{a:1,b:2}, {a:2,b:3}];
let finalArray = arr.map(function(obj){return Object.assign(obj,{c:3});})
console.log(finalArray);
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'm finding it difficult getting my head around what I think is a pretty simple task. My brain is just fried at the moment and I have a deadline. :(
I need to take all the element arrays from one multidimensional array and remove them from another multidimensional array.
Arr1 = [["Tom", "161"], ["Dick", "29"], ["Harry", "46"], ["Mike", "72"], ["Sally", "11"]];
Arr2 = [["Harry", "46"], ["Mike", "72"], ["Tom", "161"]];
So in this instance I want to take all the element arrays from Arr2 and remove them from Arr1 so that afterward Arr1 would look like this:
Arr1 = [["Dick", "29"], ["Sally", "11"]];
Does that make sense?
EDITx2: Wait, no, ignore that, I was being stupid.
Assuming you always have two elements in the array, and a "unique" element is defined as a combination of the name and the number, you can do something like this:
function(array1, array2) {
var seen = {};
var returnedArray = [];
for(var i = 0; i < array2.length; i++) {
var elements = array2[i];
seen[elements[0] + elements[1]] = true;
//an alternative to the above is to do
//seen[JSON.stringify(elements)] = true;
}
for(var i = 0; i < array1.length; i++) {
var elements = array1[i];
if(!seen[elements[0] + elements[1]]) {
returnedArray.push(elements);
}
//an alternative to the above is to do
//if(!seen[JSON.stringify(elements)]) {
// ...
//}
//
//if you took the alternate approach in the first loop
}
return returnedArray;
}
Since it's all strings you could get creative with string methods and chaining. Probably not the best performance and a bit tricky, but it works:
var arr = [["Tom", "161"], ["Dick", "29"], ["Harry", "46"], ["Mike", "72"], ["Sally", "11"]];
var remove = [["Harry", "46"], ["Mike", "72"], ["Tom", "161"]];
var result = arr
.join('|')
.replace(RegExp(remove.join('|'),'g'),'')
.match(/[^|]+/g)
.map(function(s){ return s.split(',') });
console.log(result); //=> [["Dick","29"],["Sally","11"]]
You could even try using JSON. I wouldn't recommend this for production in any case, just for fun.
Demo: http://jsbin.com/obokuy/1/edit
If you need to put together something quick, then use a nested loop to walk through the elements of Arr2 for each element in Arr1 and do a comparison on each. You can look at the answers to this question for a hint on comparing the inner arrays:
How to check if two arrays are equal with JavaScript?
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++;
}
}
}