Intersection of values of 2 arrays of objects - javascript

I have 2 arrays in the form:
array1 = [{key1: value1}, {key1: value2}, ...];
array2 = [{key2: value0}, {key2: value2}, ...];
where the object keys in both arrays are different, but the values may match. I would like to write some code that gets the intersection between the two arrays where in the above example, it should return: [value2].
I tried using:
array1.filter(function(n)) {
return array2.indexOf(n) != -1;
});
but of course I got an empty array because the keys mismatch. Can the above code be modified to ignore the object keys and match only their values?

var kiran = [];
var array1 = [{ key1: 'value1' }, { key1: 'value2' }];
var array2 = [{ key2: 'value0' }, { key2: 'value2' }];
array1.map(function(item1){
array2.map(function(item2){
if(item1.key1 === item2.key2){
kiran.push(item2.key2);
}
})
})
console.log(kiran);

How about below approach
const array1 = [{ key1: 'value1' }, { key1: 'value2' }];
const array2 = [{ key2: 'value0' }, { key2: 'value2' }];
const result = array1.filter(c => array2.findIndex(x=>x.key2 == c.key1) > -1)
console.log(result);

You could use a hash table and with a binary value. Then check if the count is equal to three, then take that key as result.
var array1 = [{ key1: 'value1' }, { key1: 'value2' }],
array2 = [{ key2: 'value0' }, { key2: 'value2' }],
hash = Object.create(null),
incHash = function (i) {
return function (o) {
Object.keys(o).forEach(function (k) {
hash[o[k]] = (hash[o[k]] || 0) | 1 << i;
});
};
},
result;
[array1, array2].forEach(function (a, i) {
a.forEach(incHash(i));
});
result = Object.keys(hash).filter(function (k) {
return hash[k] === 3;
});
console.log(result);
console.log(hash);

If you can use third party library then I suggest Lodash. An incredibly usefull utility library.
You can use _.intersectionWith() funciton to get your task done in one line
var array1 = [{ key1: 'value1' }, { key1: 'value2' }],
array2 = [{ key2: 'value0' }, { key2: 'value2' }];
var intersection = _.map(_.intersectionWith(array1, array2, function(item1,item2){
return item1.key1 === item2.key2;
}),'key1');
console.log(intersection);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js">
</script>

Related

Merge multiple arrays of objects into one array of objects JavaScript

So suppose I have a few different Arrays as follows:
var first = [{key1: x},{key1:y},{key1:z},{key1:a},{key1:b},{key1:v}, ...];
var second = [{key2: anything},{key2:...},{key2:...},{key2:...},{key2:...},{key2:...}, ...];
var third = [{key3: value},{key3:...},{key3:...},{key3:...},{key3:...},{key3:...}, ...];
var fourth = [{key4:another value},{key4:...},{key4:...},{key4:...},{key4:...},{key4:...}];
var fifth = [{key5: and another one},{key5:...},{key5:...},{key5:...},{key5:...},{key5:...}];
.
.
.
and so on...
now I would like to merge them into one array where my new objects contain one of each of the other arrays like so:
var newBigArray = [{key1: x, key2: anything, key3: value, key4: another value, key5: and another one (here in this object the first of each of the original array's objects merged into one},{here in the second object the second of each of the original array's objects...},{here the third...},{fourth},{fifth},{...},...];
I hope you get the idea.
I have tried the .push() method, the Object.assign(), and some variations of for-loops but I can't find the solution.
How would one go about this, any ideas?
You could collect all objects in an array and assign all properties of the same index to a single object.
const
first = [{ key1: 'a' }, { key1: 'b' }, { key1: 'c' }, { key1: 'd' }, { key1: 'e' }, { key1: 'f' }],
second = [{ key2: 1 } , { key2: 2 }, { key2: 3 }, { key2: 4 }, { key2: 5 }, { key2: 6 }],
third = [{ key3: 'z' }, { key3: 'y' }, { key3: 'x' }, { key3: 'w' }, { key3: 'v' }, { key3: 'u' }],
result = [first, second, third]
.reduce((r, a) => a.map((o, i) => Object.assign(r[i] || {}, o)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use the spread operator:
let first = [{x: 1, y:2}]
let second = [{x: 2, y:2}]
let third = [{x: 3, y:2}]
let fourth = [{x: 4, y:2}]
let fifth = [{x: 5, y:2}]
let finalArray = [
...first,
...second,
...third,
...fourth,
...fifth
]
console.log(finalArray)

What is best way to reset values of a dynamic object

I have a dynamic object :
input: {
key1: 'text1',
key2: 10000,
key3: 3456,
key4: 'text2',
key5: ['v1','v2','v3'] .....
}
I would like to reset it to
output
{
key1: '',
key2: 0,
key3: 0,
key4: '',
key5: []
.......
}
I didn't find any direct method to do this, I know to do this with looping. I was wondering if we have best method/best practices to acheive output.
You could take Object.assign with an object of the wanted values.
This method does not replace unknown properties. In this case, you need a new object, or you need to delete all propeties in advance.
const
values = { key1: '', key2: 0, key3: 0, key4: '', key5: [] },
input = { key1: 'text1', key2: 10000, key3: 3456, key4: 'text2', key5: ['v1','v2','v3'] };
Object.assign(input, values);
console.log(input);
A dynamic object with deleting own enumerable properties.
const
values = { key1: '', key2: 0, key3: 0, key4: '', key5: [] },
input = { foo: '42', bar: '101', key1: 'text1', key2: 10000, key3: 3456, key4: 'text2', key5: ['v1','v2','v3'] };
Object.keys(input).forEach(Reflect.deleteProperty.bind(null, input));
Object.assign(input, values);
console.log(input);
You can define all the default values in an object, and use the spread operator
let input = {key1:'text1', key2:10000, key3:3456, key4:'text2', key5:['v1','v2','v3']}
const defaultValues = {key1:'', key2:0, key3:0, key4:'', key5:[]}
input = {
...defaultValues
}
console.log(input)
You can loop through all the elements in the object and based on the type of the property we can reset it to default value. Below is the example.
let input = {key1:'text1', key2:10000, key3:3456, key4:'text2', key5:['v1','v2','v3']}
const resetData = (data) => {
let keys = Object.keys(data);
let dataCopy = {};
keys.forEach(key => {
if(Array.isArray(data[key])) {
dataCopy[key] = []
} else if(typeof data[key] === "object") {
dataCopy[key] = {}
} else if(typeof data[key] === "string") {
dataCopy[key] = ""
} else {
dataCopy[key] = 0
}
})
return dataCopy;
}
console.log(resetData(input));
input = {key6: {abc: "123"}, key7: "dummy", key8: [1, 2, 3] }
console.log(resetData(input));

Array of Objects to an Array of Values for One Key [duplicate]

This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 2 years ago.
I have an array of objects, similar to the below:
const objectArray = [
{
key1: 'value1a',
key2: 'value2a',
key3: 'value3a',
},{
key1: 'value1b',
key2: 'value2b',
key3: 'value3b',
},{
key1: 'value1c',
key2: 'value2c',
key3: 'value3c',
},
];
and I would like to get an array containing all the values stored in, say, key2.
At the moment, my code looks as follows:
const valueArray = [];
objectArray.forEach((object) => {
valueArray.push(object.key2);
});
This then results in
const valueArray = ['value2a', 'value2b', 'value2c'];
It feels like there is probably a more eloquent way to achieve the same thing, in just one line but I can't for the life of me figure out how to do that - can someone point me towards some documentation, or example code on how to do that please
Array.prototype.map()
const objectArray = [
{
key1: 'value1a',
key2: 'value2a',
key3: 'value3a',
},
{
key1: 'value1b',
key2: 'value2b',
key3: 'value3b',
},
{
key1: 'value1c',
key2: 'value2c',
key3: 'value3c',
},
];
const result = objectArray.map(obj => obj.key2);
console.log(result);
You can map objectArray:
const valueArray = objectArray.map(o => o.key2);
You can use Array#map (which creates a new array with the result of applying a callback with each element) with destructuring.
const objectArray = [
{
key1: 'value1a',
key2: 'value2a',
key3: 'value3a',
},{
key1: 'value1b',
key2: 'value2b',
key3: 'value3b',
},{
key1: 'value1c',
key2: 'value2c',
key3: 'value3c',
},
];
const res = objectArray.map(({key2})=>key2);
console.log(res);
Here is how you can do it for any key:
const objectArray = [
{
key1: 'value1a',
key2: 'value2a',
key3: 'value3a',
}, {
key1: 'value1b',
key2: 'value2b',
key3: 'value3b',
}, {
key1: 'value1c',
key2: 'value2c',
key3: 'value3c',
},
];
function getByKey(key) {
return objectArray.reduce((acc, red) => acc = [...acc, red[key]], [])
}
console.log(getByKey("key2"));

Make a new array with all the similar key values from previous array using .reduce()

How can I turn the array:
data = [
{key1: a, key2: 1},
{key1: b, key2: 2},
{key1: c, key2: 3}]
into the array:
newArray = [1, 2, 3]
using reduce?
You do not want to reduce (transform an array into a single element) but you try to map (transform an array into another array)
data = [
{key1: 'a', key2: 1},
{key1: 'b', key2: 2},
{key1: 'c', key2: 3}
]
console.log(data.map(el => el.key2))
I don't know what are you really want, but seeing your example if you want to create a new array with the values of particular key in the object with reduce you can do it something like this:
const data = [
{key1: "a", key2: 1},
{key1: "b", key2: 2},
{key1: "c", key2: 3}
];
const ans = data.reduce((prev, curr) => {
prev.push(curr.key2);
return prev;
}, []); // start with empty array
// ans: [ 1, 2, 3 ]
But, if you want to separate all the keys in a new set of arrays you can do it something like this:
const data = [
{key1: "a", key2: 1},
{key1: "b", key2: 2},
{key1: "c", key2: 3}
];
const ans = data.reduce((prev, curr) => {
Object.keys(curr).forEach((key) => {
if (!prev[key]) {
prev[key] = [curr[key]];
} else {
prev[key].push(curr[key]);
}
});
return prev;
}, {}); // start with empty object
// ans: { key1: [ 'a', 'b', 'c' ], key2: [ 1, 2, 3 ] }
As my recommendation, I prefer using for..of is cleaner and faster than reduce or forEach or map
Example of both:
// Example 1:
const ans = [];
for (const obj of data) {
ans.push(obj.key2);
}
// ans: [ 1, 2, 3 ]
// Example 2:
const ans = {};
for (const obj of data) {
for (const key of Object.keys(obj)) {
if (!ans[key]) {
ans[key] = [obj[key]];
} else {
ans[key].push(obj[key]);
}
}
}
// ans: { key1: [ 'a', 'b', 'c' ], key2: [ 1, 2, 3 ] }

Create object from forEach

I'm trying to figure out if there's a way to rewrite this code as a single object creation:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"}
];
let my_obj = {};
my_array.forEach((elem) => {
my_obj[elem.key] = elem.value;
});
What I'd like to do is something like:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"},
];
const my_obj = ...?
Is there a way to do a one-shot conversion that's equivalent to the forEach call?
You can achieve this using Array.prototype.reduce():
var my_array = [{key: 1, value:"foo"}, {key: 2, value:"bar"}];
var my_object = my_array.reduce(function(prev, curr) {
prev[curr.key] = curr.value;
return prev;
}, {});
console.log(my_object); // {"1": "foo", "2": "bar"}
Alternatively, using ES6 syntax:
const my_object = my_array.reduce((prev, curr) => {
prev[curr.key] = curr.value;
return prev;
}, {});
In ES6, you can use Object.assign:
const obj = Object.assign({}, ...my_array.map(x => ({ [x.key]: x.value })));
// Or:
const obj = Object.assign({}, ...my_array.map(({ key, value }) => ({ [key]: value })));
This converts each { key: foo, value: bar } to { foo: bar }, then uses Object.assign to merge them into one object. (The spread operator is used as Object.assign expects a variable list of arguments.)
You can use the reduce function. It should work like this:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"}
];
let my_obj = my_array.reduce(function(obj, elem) {
obj[elem.key] = elem.value;
return obj;
}, {});
// my_obj = { "1": "foo", "2": "bar" }

Categories

Resources