I have the following structure:
ley objects = {
key1: [1, 2, 3],
key2: [3,4,6],
key3: [5, 6, 7],
}
How can I combine those arrays keeping any duplicates so I will have [1, 2, 3, 3, 4, 6, 6, 6, 7]? I have tried concat but I cannot seem to find a way to do so. I have many more keys so it has to be some loop:
My attempt so far:
let arr = []
for(const [key, value] of Object.entries(objects)){
arr.concat(value);
}
Would there be a possible way to avoid this loop?
You could flat the values from the array.
let object = { key1: [1, 2, 3], key2: [3, 4, 6], key3: [5, 6, 7] },
result = Object.values(object).flat();
console.log(result);
You can use ES6 spread syntax.
const obj = {
key1: [1, 2, 3],
key2: [3, 4, 6],
};
const result = [...obj.key1, ...obj.key2];
console.log(result);
In this scenario, I'd use Array.prototype.flat() in conjunction with Object.values():
const obj = {
key1: [1, 2, 3],
key2: [3, 4, 6],
};
const result = Object.values(obj).flat();
console.log(result);
You can use Array.prototype.concat(),Array.prototype.reduce() and Object.values().
const obj = {
key1: [1, 2, 3],
key2: [3, 4, 6],
key3: [5, 6, 7]
};
const result = Object.values(obj).reduce((acc, item) => acc.concat(item), []);
console.log(result);
I assume you aim not only to merge the arrays but also to sort them as per your output. In this case, you can loop through the keys and push them in one array. After that, you can sort them by value.
const obj = {
key1: [1, 2, 3],
key2: [3,4,6]
};
const unsorted = Object.keys(obj).reduce((acc, key) => {
acc.push(...obj[key]);
return acc;
}, []);
const sorted = [...unsorted].sort((a, b) => a - b);
console.log(sorted);
This will also work
let objects = {
key1: [1, 2, 3],
key2: [3,4,6],
key3: [5, 6, 7],
}
result = Object.values(objects).join();
console.log(result);
Related
I am wondering how you would go about deleting arrays that contain the same elements in a 2 dimensional array.
For example:
let 2dArr = [ [1, 2, 3],
[3, 2, 1],
[2, 4, 5],
[4, 5, 2],
[4, 3, 1] ];
This array would delete the second and fourth elements, returning the 2d array:
returnedArr = [ [1, 2, 3],
[2, 4, 5],
[4, 3, 1] ];
How exactly could this be done, preserving the 2d array? I could only think to loop through elements, comparing elements via a sort, and deleting them as you go along, but this would result in an indexing error if an element is deleted.
1) You can easily achieve the result using reduce and Set as:
let twodArr = [
[1, 2, 3],
[3, 2, 1],
[2, 4, 5],
[4, 5, 2],
[4, 3, 1],
];
const set = new Set();
const result = twodArr.reduce((acc, curr) => {
const key = [...curr].sort((a, b) => a - b).join();
if (!set.has(key)) {
set.add(key);
acc.push(curr);
}
return acc;
}, []);
console.log(result);
2) You can also use filter as:
let twodArr = [
[1, 2, 3],
[3, 2, 1],
[2, 4, 5],
[4, 5, 2],
[4, 3, 1],
];
const set = new Set();
const result = twodArr.filter((curr) => {
const key = [...curr].sort((a, b) => a - b).join();
return !set.has(key) ? (set.add(key), true) : false;
});
console.log(result);
const seen = []
const res = array.filter((item) => {
let key = item.sort().join()
if(!seen.includes(key)){
seen.push(key)
return item
}
})
console.log(res)
You can use hash map
let arr = [ [1, 2, 3], [3, 2, 1],[2, 4, 5],[4, 5, 2],[4, 3, 1] ];
let obj = {}
let final = []
for(let i=0; i<arr.length; i++){
// create a key
let sorted = [...arr[i]].sort((a,b)=> a- b).join`,`
// check if this is not present in our hash map
// add value to final out and update hash map accordingly
if(!obj[sorted]){
obj[sorted] = true
final.push(arr[i])
}
}
console.log(final)
Using Array.prototype.filter() and a Set as thisArg
let arr = [ [1, 2, 3],
[3, 2, 1],
[2, 4, 5],
[4, 5, 2],
[4, 3, 1] ];
let res = arr.filter(function(e){
const sorted = [...e].sort((a,b) => a-b).join('|');
return this.has(sorted) ? false : this.add(sorted)
},new Set)
console.log(res)
I have an array of arrays, and I want to map over it and just return the values of arrays, but when I map over it and log the result, it's just an array and I don't know how to map over my array and use it in other places.
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const arrMap = arr.map((it) => it.map((itm) => itm));
console.log(arrMap);
//what I expected 1,2,3,4,5,6 , ...
//what I got [Array(3), Array(3), Array(3)]
Actually, I need the values for using them in somewhere else, but I don't know what to do.
I also used function for this but when I return the values and log them It's undefined:
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const arrMap = (arr) => {
arr.forEach((element) => {
console.log(element);
//In here, everything works fine
return element;
});
};
console.log(arrMap);
//what I got undefined
Use flatMap -
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const arrMap = arr.flatMap(m => m);
console.log(arrMap);
Why it won't work : map() is supposed to run on each element of an array and return a transformed array of the same length. You have three elements in your input array and will always get three elements in your mapped array.
Your expectations can be met by tweaking your code with forEach() if you want. With forEach() there is nothing returned and you will have to start with a separate array variable. Below code uses ...
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
let arrMap = [];
arr.forEach((it) => arrMap.push(...it));
console.log(arrMap);
But flatMap() is already there:
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
let ans = arr.flatMap(x => x);
console.log(ans);
Use flat if you just want to flatten the array:
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
console.log(arr.flat());
Use flatMap if you want to do something with each element before the array gets flattened.
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const arrMap = arr.flatMap((el) => {
el.forEach((n) => console.log(n));
return el;
});
console.log(arrMap);
forEach doesn't return anything it's like a for loop but for array only.
Since you have double array you should flat it by using flatMap
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const arrMap = arr.flatMap((it) => it);
console.log(arrMap);
I have an object with a string type key, and an array type value, the object looks like this
myObj = { a: [1, 2, 3], b: [5. 6], c:[9] }
I want to add a integer inside the array of a certain key, let's say for example I want add the number 7 inside the array of key a, so the object becomes myObj = { a: [1, 2, 3, 7], b: [5, 6], c: [9] }
I tried doing something like myObj["a"].push(7);, but this completely changed the structure of myObj.
How should I implement this to accomplish my goal?
const myObj = { a: [1, 2, 3], b: [5, 6], c:[9] }
myObj["a"].push(7);
console.log(myObj)
Use follow as code:
const myObj = { a: [1, 2, 3], b: [5, 6], c:[9] }
myObj.a.push(7);
console.log(myObj)
I've Tried These:
let myObj = {a: [1, 2, 3], b: [5, 6], c:[9]};
myObj.a.push(7); //Worked Correctly Will Return length of "a" Array
myObj["a"].push(7); //Worked
Given the following object
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]}
is it possible, using Object.keys (no loop), to get key (low/medium/high) by one of the corresponding values?
Maybe something like this:
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
function getKey(n) {
return Object.keys(obj).find(k => obj[k].includes(n));
}
If you would really like to avoid for loop, you can use Array#reduce instead.
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const fn = (value, arr) =>
Object.entries(arr)
.reduce((s, [key, a]) => (a.indexOf(value) > -1 ? key : s), null);
console.log(fn(7, obj));
console.log(fn(1, obj));
You can define a function to return the key according to the value passed.
the function uses Object.keys and Array.find()
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const findKeyByValue = (value)=>{
return Object.keys(obj).find(key => obj[key].find(element => element === value))
}
console.log(findKeyByValue(8))
It's not possible to do this without a custom approach, there are a lot of ways for accomplishing what you want.
This approach uses the Proxy object to find the key by the accessed property and keeps the entries to be able to provide quick access.
const obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]},
decorate = (o) => {
const entries = Object.entries(o);
return new Proxy(o, {
get(_, accessedProperty) {
let [key] = (entries.find(([_, values]) => values.includes(+accessedProperty)) || []);
return key;
}
});
},
decoratedObj = decorate(obj);
console.log(decoratedObj[1]);
console.log(decoratedObj[4]);
console.log(decoratedObj[10]);
console.log(decoratedObj[11]);
You can do it with Object.keys, Object.values, Array#findIndex and Array#some.
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
function mySearch(obj,search) {
return Object.keys(obj)[(Object.values(obj).findIndex(el => el.some(val => val===search)))];
}
console.log(mySearch(obj, 5));
console.log(mySearch(obj, 8));
You're looking for a different data structure than a basic object. Have a look at the bidirectional map. This is a data strucure that allows you to look up values by their key, and keys by their value.
I can recommend this implementation. It's part of mnemonist, which has a bunch of handy data structures for different use cases!
import BiMap from 'mnemonist/bi-map';
const obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const lookupTable = BiMap.from(obj);
console.log(lookupTable.get('low'))
// > [1,2,3]
console.log(lookupTable.inverse.get([1,2,3]))
// > 'low'
I'm trying to write a function that finds arrays that are not common to both nested arrays. Also note the arrays will be pre-sorted.
var array1 = [ [1, 2, 3], [2, 3, 4] [5, 6, 7] ];
var array2 = [ [1, 2, 3], [2, 3, 4] [7, 8, 9] ];
For the above two arrays the function should return [5, 6, 7] and [7, 8, 9].
So far I've got:
function arrayIntersection(array1, array2) {
return array2.filter(function(values1) {
return array2.indexOf(values1) === -1;
});
};
But it doesn't seem to be working. I'm guessing the indexOf() isn't doing a compares correctly. I'm trying to avoid using ES6 or polyfills.
You can use the built in .every() and .filter() array methods to accomplish this task.
var array1 = [ [1, 2, 3], [2, 3, 4], [5, 6, 7] ];
var array2 = [ [1, 2, 3], [2, 3, 4], [7, 8, 9] ];
function compareArrays(arr1, arr2) {
if (arr1.length !== arr2.length) {
return false;
} else {
return arr1.every(function(elem) {
return arr2.indexOf(elem) > -1;
});
}
}
function filterUnique(arr1, arr2) {
return arr1.filter(function(elem) {
return arr2.every(function(_elem) {
return !compareArrays(_elem, elem);
});
});
}
function filterIntersection(arr1, arr2) {
var uniqueToArr1 = filterUnique(arr1, arr2);
var uniqueToArr2 = filterUnique(arr2, arr1);
return [].concat(uniqueToArr1, uniqueToArr2);
}
console.log(filterIntersection(array1, array2));
First, you referenced the wrong array in your filter. To fix the comparison, you could turn the arrays to json. You will also need to run the filter against the second array and join the answers.:
var array1 = [ [1, 2, 3], [2, 3, 4], [5, 6, 7] ];
var array2 = [ [1, 2, 3], [2, 3, 4], [7, 8, 9] ];
function arrayIntersection(input1, input2) {
var input2NotInInput1 = input2.filter(function(values1) {
return input1.map(function(val) { return JSON.stringify(val); }).indexOf(JSON.stringify(values1)) === -1;
});
var input1NotInInput2 = input1.filter(function(values1) {
return input2.map(function(val) { return JSON.stringify(val); }).indexOf(JSON.stringify(values1)) === -1;
});
return input1NotInInput2 .concat( input2NotInInput1 );
};
console.log(arrayIntersection(array1, array2));
It's not a best option but it works
var ar1 = [
[1, 2, 3],
[2, 3, 4],
[5, 6, 7]
];
var ar2 = [
[1, 2, 3],
[2, 3, 4],
[7, 8, 9]
];
function arrayIntersection(array1, array2) {
return array2.filter(function(values1) {
return !array1.some(v => JSON.stringify(v) === JSON.stringify(values1));
});
};
var result = arrayIntersection(ar1, ar2);
console.log(result);