How to loop through array of objects and make key value pairs? - javascript

I have an array of objects like this:
let someObj = {
items: [{
id: '12',
value: true
}, {
id: '34',
value: true
}, {
id: '56',
value: false
}]
}
I want add this to an exiting object, where id is a key of this object, like this:
let obj = {
someKey: someValue,
'12': true,
'34': true,
'56': false,
}

You may achieve your goal using Array#reduce as follows:
const input = {
items: [{
id: '12',
value: true
}, {
id: '34',
value: true
}, {
id: '56',
value: false
}]
}
const output = input.items.reduce((o, {
id,
value
}) => (o[id] = value, o), {})
console.log(output)
Also, and maybe the simplest approach might be using Array#map to turn objects into pairs and then convert them into an object using Object.fromPairs:
const input = {
items: [{
id: '12',
value: true
}, {
id: '34',
value: true
}, {
id: '56',
value: false
}]
}
const output = Object.fromEntries(input.items.map(({
id,
value
}) => [id, value]))
console.log(output)
Finally, here's a functional approach:
// Composes two functions
const compose = f => g => x => f (g (x))
// Given the key-value pairs of some object with 2 properties, maps a pair of values
const values = ([[, x], [, y]]) => [x, y]
// Turns an object of two properties into a pair of property values
const entry = compose (values) (Object.entries)
// Turns many objects of two properties, into an object on which
// keys are first properties' values, and vaules the second properties' values.
const keyValueObject = xs => Object.fromEntries (xs.map (entry))
const input = {
items: [{
id: '12',
value: true
}, {
id: '34',
value: true
}, {
id: '56',
value: false
}]
}
const output = keyValueObject (input.items)
console.log(output)

You can iterate each item from items and create a new object as shown below.
let someObj = {
items: [{
id: '12',
value: true
}, {
id: '34',
value: true
}, {
id: '56',
value: false
}]
}
const newObj = {};
someObj.items.map(item =>{
newObj[item.id]= item.value;
});
console.log(newObj);

Use map and Object.values will simplify.
const output = arr => Object.fromEntries(arr.map(Object.values));
let someObj = {
items: [
{
id: "12",
value: true,
},
{
id: "34",
value: true,
},
{
id: "56",
value: false,
},
],
};
console.log(output(someObj.items));

First, you can transform the itens into "KV" entries
> someObj.items.map(({id, value}) => [id, value])
[ [ '12', true ], [ '34', true ], [ '56', false ] ]
Then turn it into Object
> Object.fromEntries(someObj.items.map(({id, value}) => [id, value]))
{ '12': true, '34': true, '56': false }
You can do a function
> let ObjectFromMapping = (vs, mapping) => Object.fromEntries(vs.map(mapping))
> ObjectFromMapping(someObj.items, ({id, value}) => [id, value])
{ '12': true, '34': true, '56': false }
Maybe turn vs into a iterable is a good idea
> let ObjectFromMapping = (vs, mapping) => Object.fromEntries([... vs].map(mapping))
> ObjectFromMapping("abc", (char, idx) => [idx, char])
{ '0': 'a', '1': 'b', '2': 'c' }
Then your function will work on any iterable

Related

How to use some lodash method to check if one property doesnt match within two arrays using javascript?

i have 2 array of objects like so,
const initial = [
{
id: '1',
value: '1',
},
{
id: '2',
value: '2',
}
]
const current = [
{
id: '1',
value: '3',
},
{
id: '2',
value: '2',
},
]
these two arrays are almost the same.
i want to check if the current array has value different than the initial array with same id.
so if atleast one of the object in current has value different from the initial value then it should return true. if not false.
so in above example current array with id 1 has value 3 which is different from initial value with id '1'.
i was trying to do something like below,
const output = current.filter(item => some(initial, {id: item.id, value: !item.value}))
but this doesnt seem to be the right way. could someone help me with this. thanks.
Using Map and Array#map, save the id-value pairs of initial
Using Array#some, iterate over current to compare
const _isDifferent = (initial = [], current = []) => {
const map = new Map( initial.map(({ id, value }) => ([id, value])) );
return current.some(({ id, value }) => map.get(id) !== value);
}
const
initial = [ { id: '1', value: '1' }, { id: '2', value: '2' } ],
current = [ { id: '1', value: '3' }, { id: '2', value: '2' } ];
console.log( _isDifferent(initial, current) );
Based on your code,we can compare the length to find if it has different value
let checkDiffArray = (arr1,arr2) =>
arr1.filter(a1 => arr2.some(a2 => a2.id === a1.id && a2.value === a1.id)).length != arr2.length
const initial = [
{
id: '1',
value: '1',
},
{
id: '2',
value: '2',
}
]
const current = [
{
id: '1',
value: '3',
},
{
id: '2',
value: '2',
},
]
let checkDiffArray = (arr1,arr2) => arr1.filter(a1 => arr2.some(a2 => a2.id === a1.id && a2.value === a1.id)).length != arr2.length
console.log(checkDiffArray(initial,current))
You can use the differenceWith combined with the isEqual
const initial = [
{ id: '1', value: '1' },
{ id: '2', value: '2' }
]
const current = [
{ id: '1',value: '3' },
{ id: '2',value: '2' },
]
const output = Boolean(_.differenceWith(current, initial, _.isEqual).length);
console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

How to remove data with same id in an array of object using javascript?

in an arry of objects i want to remove object which have same id (duplicated data) using javascript.
below is the input array
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
so as you see from above array there are duplicating data with id '1' and '2'.
if there is similar id i want include only one
so the expected output is like below,
const output = [
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
]
how can i do this. could someone help me with this. i am new to programming thanks.
You can use reduce to filter data from the array based on some condition like bellow
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = input.reduce((accumulator, current) => {
let exists = accumulator.find(item => {
return item.id === current.id;
});
if(!exists) {
accumulator = accumulator.concat(current);
}
return accumulator;
}, []);
console.log(result);
Similar to this answer. You will have to change the const to let while declaring input though, or use a new variable I suppose.
filtered_input = input.filter((value, index, self) =>
index === self.findIndex((t) => (
t.id === value.id
))
)
There is a lot of good approachs here.
Here is my approach for removing matching property from the original array and sending it back in the return if found.
I prefer to use this one, if you are looping through a external array and matching them, this way you dont need to loop through the whole array again and again for each, because while you are finding the matches it keeps removing them from the original array, increasing performance.
Note that this will return the first match found
let id = "601985b485d9281d64056953"
let contacts = [{
...,
parent: "601985b485d9281d64056953",
...,
},
{
...,
parent: "601985b485d9281d64065128",
...,
}
]
function findAndRemoveObjectFromArray(array, internalProperty, externalProperty, convertType = "string", returnObject = false) {
let objIndex = -1
if (convertType === "string") objIndex = array.findIndex((obj) => String(obj[`${internalProperty}`]) === String(externalProperty));
if (convertType === "number") objIndex = array.findIndex((obj) => Number(obj[`${internalProperty}`]) === Number(externalProperty));
if (objIndex > -1) {
const object = array.splice(objIndex, 1);
if (returnObject) return object.shift()
return object
}
return [];
}
let currentContact = findAndRemoveObjectFromArray(contacts, "parent", id, 'string', true)
// Results:{..., parent: "601985b485d9281d64056953",...}
you could use Set to get rid of the duplicate data like this
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = [...new Set(input.map(JSON.stringify))].map(JSON.parse)
console.log(result)
Below is another approach
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
];
const uniqueIds = new Set();
const uniqueList = input.filter(element => {
const isDuplicate = uniqueIds.has(element.id);
uniqueIds.add(element.id);
return !isDuplicate;
});
console.log(uniqueList);

Create new array from existing array with unique joined values from existing array

Does anyone know how I can create a new array from existing array with unique joined values from existing array?
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
//
//
const newArrayBasedOnOriginalArray = [
{ value: 'red/small/modern' },
{ value: 'red/small/classic' },
{ value: 'red/medium/modern' },
{ value: 'red/medium/classic' },
{ value: 'blue/small/modern' },
{ value: 'blue/small/classic' },
{ value: 'blue/medium/modern' },
{ value: 'blue/medium/classic' },
];
I calculated that the length of the new array should always be as following:
// length of new array
const lengthOfNewArray = originalArray
.map((value) => {
return value.length;
})
.reduce((current, old) => {
return current * old;
});
//
//
console.log('length of new array:', lengthOfNewArray); // 8
You can do it recursively
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
const getPossibleCombination = (currentValue, arraysRemaining) => {
if(arraysRemaining.length === 0) return currentValue
const values = []
const firstArray = arraysRemaining[0]
firstArray.forEach(({value}) => {
values.push(getPossibleCombination(`${currentValue}/${value}`, arraysRemaining.slice(1, arraysRemaining.length)))
})
return values.flat()
}
const values = getPossibleCombination('', originalArray)
console.log(values)
In this case, you do not necessarily need recursion. Array.reduce() greatly does the job:
const originalArray = [
[
{ value: 'red', id: 99 },
{ value: 'blue', id: 100 },
],
[
{ value: 'small', id: 101 },
{ value: 'medium', id: 102 },
],
[
{ value: 'modern', id: 103 },
{ value: 'classic', id: 104 },
],
];
const newArray = originalArray
.map(elem => elem.map(({value}) => value))
.reduce((acc, cur) => acc.flatMap(seq => cur.map(part => `${seq}/${part}`)))
.map(elem => ({value: elem}))
console.log(newArray)
Aside from the initial and final map(), used to simplify the input objects, what I am doing is continuously combining the accumulator with the next sub-array.
For each object in the sub-array I duplicate every object in the accumulator, using the nested map(). flatMap() is used to keep the accumulator flat, with a simple map() the accumulator depth would increase every time we visit a new sub-array.
First of all if values in each of your arrays is unique then the concatenated values will be unique as well. After you make sure values are unique you can use this code to create combinations of strings:
const newArrayBasedOnOriginalArray = originalArray.reduce(
(acc, el) =>
el.flatMap(({ value }) =>
acc.length ? acc.map((str) => str + "/" + value) : value
),
[]
).map(value=>({value});

Filter JSON with desired keys

I have an array of objects sample for example :
const data = [
{
Name: 'test_1',
Value: '175',
Description: 'desc_1'
},
{
Name: 'test_2',
Value: '175',
Description: 'desc_2'
}
]
And an env file where I mark the data I want :
Name=true
Value=true
Description=false
How do I filter out the data file to only return the values of the keys Name and Value?
Desired output :
[
{
Name: 'test_1',
Value: '175'
},
{
Name: 'test_2',
Value: '175',
}
]
There are different ways in order to achieve the required output, here I'm making use of Array.map and Array.reduce methods.
const data = [{ Name: 'test_1', Value: '175', Description: 'desc_1', }, {Name: 'test_2', Value: '176', Description: 'desc_2', }];
//In order to access from the env file
/*
const fields = {
Name: process.env.Name,
Value: process.env.Value,
Description: process.env.Description
}
*/
//For the snippet purpose i'm using this hardcoded values
const fields = {
Name: true,
Value: true,
Description: false
}
//Convert the object to an array of keys whose values are needed from the original data
const getConfigData = fields => Object.keys(fields).filter(key => fields[key])
let config = getConfigData(fields);
const getSelectedKeyValues = (data, config) => {
return data.map(obj => config.reduce((acc, c) => (acc[c] = obj[c], acc), {}));
}
console.log("Name & Value:", getSelectedKeyValues(data, config));
.as-console-wrapper {
max-height: 100% !important;
}
You can do it like this:
const data = [
{ Name: 'test_1', Value: '175', Description: 'desc_1' },
{ Name: 'test_2', Value: '175', Description: 'desc_2' }
]
let results = data.map((item) => {
new_item = {};
if (process.env.Name) new_item.Name = item.Name;
if (process.env.Value) new_item.Value= item.Value;
if (process.env.Description) new_item.Description= item.Description;
return new_item;
})
Since your example is a JS array and no JSON string, you can use map:
const result = data.map(d => { return {Name: d.name, Value: d.Value }});
Another solution would be filtering the objects entries when mapping and creating a new object from those entries.
const data = [{
Name: 'test_1',
Value: '175',
Description: 'desc_1'
},
{
Name: 'test_2',
Value: '175',
Description: 'desc_2'
}
]
const status = {
Name: true,
Value: true,
Description: false
}
// props you want to keep
const keep = Object.keys(status).filter((k) => status[k]);
const result = data.map((d) => {
// create object from entries based on what you want to keep
return Object.fromEntries(Object.entries(d).filter(([k]) => {
return keep.includes(k)
}));
})
console.log(result);

Javascript lodash Filter Objects in Array based on value

I have the following array of objects:
var array = [
{
name: isSale,
value: true
},
{
name: isSale,
value: false
},
{
name: isNew,
value: true
}
]
I need to filter the array so that I have only 2 objects at the end:
var array = [
{
name: isSale,
value: true
},
{
name: isNew,
value: true
}
]
Meaning if I have both true and false values for the same name (isSale) I need to leave the object with the true value.
But if my array looks like this:
var array = [
{
name: isSale,
value: false
},
{
name: isNew,
value: true
}
]
meaning there is no duplicate isSale object it should stay like this and the object with the false value should not be removed from the array.
I prefer a solution with ES5 (you can write it in ES6/7 and transpile it with babel to ES5) and you can use lodash as well.
Thank you for the suggestions and cheers!
You could seach for same name in the result set and replace if the former value is false.
const
filter = array => array.reduce((r, o) => {
var index = r.findIndex(({ name }) => name === o.name)
if (index === -1) r.push(o);
else if (!r[index].value) r[index] = o;
return r;
}, []),
array1 = [{ name: 'isSale', value: true }, { name: 'isSale', value: false }, { name: 'isNew', value: true }],
array2 = [{ name: 'isSale', value: false }, { name: 'isNew', value: true }];
console.log(filter(array1));
console.log(filter(array2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories