Pushing value to array that is the value of an object - javascript

I have the following structure:
let mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
and I want to add this piece of data
const issueTypes = ["4000"]
to each of the arrays of the object keys ending with this
mappings = {
"1002": ["1000", "1003", "4000"],
"2000": ["2001", "2002", "4000"]
}
This is what I have so far:
mappings = Object.keys(mappings).reduce((prev, curr, index) => {
console.log("prevous", prev)
console.log("curret", curr)
return ({
...prev, [curr]: //unsure of this part which is kind of crucial
})}, mappings)
Any help would be really appreciated

Why not just iterate over the values of the object, and push?
const mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
for (const arr of Object.values(mappings)) {
arr.push(...issueTypes);
}
console.log(mappings);
If it must be done immutably, map the entries of the object to a new array of entries, while spreading the new issueTypes into the value.
const mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
const newMappings = Object.fromEntries(
Object.entries(mappings).map(
([key, arr]) => [key, [...arr, ...issueTypes]]
)
);
console.log(newMappings);

The procedure is quite simple. What you need to do is this —
Iterate over each value of the mappings object.
Push the new value
Refer to the following code and adapt —
let mappings = {
"1002": ["1000", "1003"],
"2000": ["2001", "2002"]
}
const issueTypes = ["4000"]
for (const item in mappings) {
mappings[item].push(issueTypes[0])
}
Hope this helps! :)

Related

How to update an object value in array of objects when the keys are same

I have an Array of objects and one object
const filterArray = [{bestTimeToVisit: 'Before 10am'}, {bestDayToVisit: Monday}]
This values are setting in a reducer and the payload will be like
{bestTimeToVisit: 'After 10am'}
or
{bestDayToVisit: Tuesday}.
So what I need is when I get a payload {bestTimeToVisit: 'After 10am'} and if bestTimeToVisit not in filterList array, then add this value to the filterList array.
And if bestTimeToVisit already in the array with different value, then replace the value of that object with same key
if(filterArray.hasOwnProperty("bestTimeToVisit")) {
filterArray["bestTimeToVisit"] = payload["bestTimeToVisit"];
} else {
filterArray.push({"bestTimeToVisit": payload["bestTimeToVisit"]});
}
I convert the object array into a regular object and then back into an object array. makes things less complicated. I'm making the assumption each object coming back only has one key/value and that order doesnt matter.
const objectArraytoObject = (arr) =>
arr.reduce((acc, item) => {
const key = [Object.keys(item)[0]];
return { ...acc, [key]: item[key] };
}, {});
const newValues = [{ someKey: 'something' }, { bestDayToVisit: 'Tuesday' }];
const filterArray = [
{ bestTimeToVisit: 'Before 10am' },
{ bestDayToVisit: 'Monday' },
];
const newValuesObj = objectArraytoObject(newValues);
const filterObj = objectArraytoObject(filterArray);
const combined = { ...filterObj, ...newValuesObj };
const combinedToArray = Object.keys(combined).map((key) => ({
[key]: combined[key],
}));
console.log(combinedToArray);
Need to iterate over the array and find objects that satisfy for modification or addition if none are found.
function checkReduced(filterrray,valueToCheck="After 10am"){
let isNotFound =true;
for(let timeItem of filterrray) {
if(timeItem.bestTimeToVisit && timeItem.bestTimeToVisit !== valueToCheck) {
timeItem.bestTimeToVisit=valueToCheck;
isNotFound=false;
break;
}
}
if(isNotFound){filterrray.push({bestTimeToVisit:valueToCheck})}
}
const filterArray = [{bestDayToVisit: "Monday"}];
checkReduced(filterArray,"After 9am");//calling the function
const updateOrAdd = (arr, newItem) => {
// get the new item key
const newItemKey = Object.keys(newItem)[0];
// get the object have the same key
const find = arr.find(item => Object.keys(item).includes(newItemKey));
if(find) { // the find object is a reference type
find[newItemKey] = newItem[newItemKey]; // update the value
} else {
arr.push(newItem); // push new item if there is no object have the same key
}
return arr;
}
// tests
updateOrAdd([{ a: 1 }], { b: 2 }) // => [{ a: 1 }, { b: 2 }]
updateOrAdd([{ a: 1 }], { a: 2 }) // => [{ a: 2 }]

How can I store previous values instead of storing the value in array of objects in react state

I am storing the prev values in an array of objects, for example [{ActFollow: 'BlN'},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}] I want to store the key and values in an object like this {ActFollow: 'BlN',ActSendGift: 'BlY', ActSubscribe: 'BlY'}
const [activityTypes, setActivityTypes] = useState<any>([]); // state
.then((response: any) => {
setActivityTypes((oldArray: any) => [
...oldArray,
{[item.channelSettingTypeId]: response.settingValue},
]);
});
How about this, if the nesting is only one level deep
const data = [{ActFollow: 'BlN',ActSendGift: 'BlY', ActSubscribe: 'BlY'}]
console.log([{...data[0],"hey" : "world"}])
const items = [{ActFollow: 'BlN'},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}]
let object = {}
items.forEach(item=>{
for (const [key, value] of Object.entries(item)) {
object = {
...object,
[key]: value
}
}
})
console.log(object)
You can use this simple idea in React also. Just hold on the default empty object in state and update the object.
You can reduce the array of objects into an object.
You can do it by spreading (...) the current object into the resultant object, as shown below:
const
arrOfObjs = [{ ActFollow: "BlN" }, { ActSendGift: "BlY" }, { ActSubscribe: "BlY" }],
obj = arrOfObjs.reduce((res, o) => ({ ...res, ...o }), {});
console.log(obj);
You can also do it using Object.assign, as shown below:
const
arrOfObjs = [{ ActFollow: "BlN" }, { ActSendGift: "BlY" }, { ActSubscribe: "BlY" }],
obj = arrOfObjs.reduce((res, o) => Object.assign(res, o), {});
console.log(obj);
Use Spread Operator
const items = [{ActFollow: 'BlN', Anurag: 26},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}]
let obj ={}
items.forEach((item) => {
obj = {
...obj,
...item
}
})
console.log(obj)

Create an array of object properties for each item that has the same key

I'm merging two objects together to create a filter object. However I want to group the merged objects property values where the keys are the same.
So...
[{category: 'furniture'}, {category: 'mirrors'}, {availability: 'in_stock'}]
becomes
[{category: ['furniture', 'mirrors']}, {availability: 'in_stock'}]
any ideas?
With lodash you merge the entire array to a new object by spreading into _.mergeWith(). The customizer should use empty arrays as default values for the current values, and concat the values. Use _.map() to convert back to an array.
const data = [{category: 'furniture'}, {category: 'mirrors'}, {availability: 'in_stock'}];
const result = _.map(
_.mergeWith({}, ...data, (a = [], b = [], key) => a.concat(b)),
(val, key) => ({ [key]: val })
)
console.log(result)
<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>
Using vanilla JS, reduce the array to a Map using the objects' keys as the keys of the Map, with an empty array as the value, and push the objects' values into the arrays. Use Array.from() to convert the Map to an array.
const data = [{category: 'furniture'}, {category: 'mirrors'}, {availability: 'in_stock'}];
const result = Array.from(
data.reduce((acc, obj) => {
Object.entries(obj)
.forEach(([key, val]) => {
if(!acc.has(key)) acc.set(key, [])
acc.get(key).push(val)
})
return acc
}, new Map()),
([key, val]) => ({ [key]: val })
)
console.log(result)
You can use reduce like this:
const data = [
{ category: 'furniture' },
{ category: 'mirrors' },
{ availability: 'in_stock' }
];
const result = data.reduce(
(a, x) => {
const key = Object.keys(x)[0]; // find the key of the current object
if (!a.tmp[key]) { // if the current key doesn't exist in the lookup object (tmp) yet ...
a.tmp[key] = []; // create an empty array in the lookup object for the current key
a.result.push({ [key]: a.tmp[key] }); // push the current object to the result
}
a.tmp[key].push(x[key]); // push the current value to the array
return a;
},
{ result: [], tmp: {} },
).result;
console.log(result);
I'm sure there are easier ways to achieve this, but that's the best I can come up with right now.
we can also achieve this by using forEach loop :
const input = [{category: 'furniture'}, {category: 'mirrors'}, {availability: 'in_stock'}];
const resultObj = {};
const resultArr = [];
input.forEach((obj) => {
resultObj[Object.keys(obj)[0]] = [];
})
input.forEach((obj) => {
resultObj[Object.keys(obj)[0]].push(obj[Object.keys(obj)[0]]);
resultArr.push(resultObj);
})
console.log([...new Set(resultArr)]);
Another one reduce solution
const arr = [{category: 'furniture', category2: 'furniture2'}, {category: 'mirrors'}, {availability: 'in_stock'}]
const result = Object.values(arr
.flatMap((obj) => Object.entries(obj))
.reduce((acc, [key, value]) => {
acc[key] = acc[key]
? {[key]: [...acc[key][key], value] }
: {[key]: [value] }
return acc;
}, {}));
console.log(result)
.as-console-wrapper{min-height: 100%!important; top: 0}
A generic implementation could achieve a merger of any kind of objects regardless of amount and kind of an(y) object's property names.
Since the result of such an implementation is an object, one needs additional treatment in order to cover the OP's requirement(s).
function mergeAndCollectItemEntries(result, item) {
// return the programmatically aggregated merger/result.
return Object
// get an item's entry array.
.entries(item)
// for each key-value pair ...
.reduce((merger, [key, value]) => {
// ... access and/or create a `key` specific array ...
// ... and push `value` into this array.
(merger[key] ??= []).push(value);
// return the programmatically aggregated merger/result.
return merger;
}, result);
}
const sampleData = [
{ category: 'furniture' },
{ category: 'mirrors' },
{ availability: 'in_stock' },
];
const mergedData = sampleData
.reduce(mergeAndCollectItemEntries, {});
const mergedDataList = Object
.entries(
sampleData
.reduce(mergeAndCollectItemEntries, {})
)
.map(entry => Object.fromEntries([entry]));
//.map(([key, value]) => ({ [key]: value }));
console.log({
sampleData,
mergedData,
mergedDataList,
});
console.log(
Object
.entries([
{ category: 'furniture', foo: 'baz' },
{ category: 'mirrors', bar: 'bizz' },
{ availability: 'in_stock', bar: 'buzz' },
].reduce(
mergeAndCollectItemEntries, {}
)
).map(
([key, value]) => ({ [key]: value })
//entry => Object.fromEntries([entry])
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Another approach here with building an tracking object to merge the values.
Handle the cases of single value keep as string and multiple values as array per the expected output.
const merge = (arr, output = {}) => {
arr.forEach((item) => {
const [[key, val]] = Object.entries(item);
if (key in output) {
output[key] = Array.isArray(output[key])
? output[key].concat(val)
: [output[key]].concat(val);
} else {
output[key] = val;
}
});
return Object.entries(output).map(([key, val]) => ({ [key]: val }));
};
const data = [
{ category: "furniture" },
{ category: "mirrors" },
{ availability: "in_stock" },
];
console.log(merge(data));

Loop through array for each value from another array

How can I loop through this array:
const counts = [
"900,google.com",
"60,mail.yahoo.com",
"10,mobile.sports.yahoo.com",
"40,sports.yahoo.com",
"300,yahoo.com",
"10,stackoverflow.com",
"20,overflow.com",
"5,com.com",
"2,en.wikipedia.org",
"1,m.wikipedia.org",
"1,mobile.sports",
"1,google.co.uk",
];
taking each value from this array?
const uniqueDomains = [
'google.com',
'com',
'mail.yahoo.com',
'yahoo.com',
'mobile.sports.yahoo.com',
'sports.yahoo.com',
'stackoverflow.com',
'overflow.com',
'com.com',
'en.wikipedia.org',
'wikipedia.org',
'org',
'm.wikipedia.org',
'mobile.sports',
'sports',
'google.co.uk',
'co.uk',
'uk'
]
I need to find out if string from counts array includes string from uniqueDomains array.
Then push it to the empty object as a key value pairs, where value
is going to be the number in the beginning of the each string from counts array.
I tried this code but it give me wrong result in my object's values(since I am looping twice)
I need kind of avoid looping twice, but I am not sure how.
Example com is mentioned 8 time in counts array, which means result should be this {com: 1345}
Here is my code:
const finalObject = {}
uniqueDomains.forEach((dom) => {
counts.forEach((cnt) => {
if (cnt.includes(dom)) {
const num = parseInt(cnt);
sumArr.push(num);
const res = sumArr.reduce((acc, cur) => {
return acc + cur;
});
finalObject[dom] = res;
}
});
});
Theres not really any avoiding looping twice (at least), but you can certainly make your code a bit easieer by first turning the count array into an array of val & domain separately.
const countIdx = counts.map(x => {
const [val,domain] = x.split(",");
return {val:parseInt(val,10), domain}
});
Then its just a case of looping the uniqueDomain array and finding all the domaion which match and summing up the val
const result = uniqueDomains.reduce( (res, d) => {
const count = countIdx.filter(x => x.domain.includes(d)).reduce( (acc,x) => acc + x.val,0);
return {...res, [d]:count}
},{});
Live example follows:
const counts = [
"900,google.com",
"60,mail.yahoo.com",
"10,mobile.sports.yahoo.com",
"40,sports.yahoo.com",
"300,yahoo.com",
"10,stackoverflow.com",
"20,overflow.com",
"5,com.com",
"2,en.wikipedia.org",
"1,m.wikipedia.org",
"1,mobile.sports",
"1,google.co.uk",
];
const uniqueDomains = [
'google.com',
'com',
'mail.yahoo.com',
'yahoo.com',
'mobile.sports.yahoo.com',
'sports.yahoo.com',
'stackoverflow.com',
'overflow.com',
'com.com',
'en.wikipedia.org',
'wikipedia.org',
'org',
'm.wikipedia.org',
'mobile.sports',
'sports',
'google.co.uk',
'co.uk',
'uk'
]
const countIdx = counts.map(x => {
const [val,domain] = x.split(",");
return {val:parseInt(val,10), domain}
});
const result = uniqueDomains.reduce( (res, d) => {
const count = countIdx.filter(x => x.domain.includes(d)).reduce( (acc,x) => acc + x.val,0);
return {...res, [d]:count}
},{});
console.log(result);
Maybe try something like:
let finalObject = {}
uniqueDomains.forEach((dom) => {
finalObject[dom] = 0;
counts.forEach((cnt) => {
if (cnt.includes(dom)) {
finalObject[dom] += parseInt(cnt);
}
});
});

How to create object from another object JavaScript

How to convert first variable entries into newEntries variable?
let entries = {
"app": "/main/application/src/app/src/pages/app/src/index.js",
"app1": "/main/application/src/app/src/pages/app/src/app1.js",
"app2": "/main/application/src/app/src/pages/app/src/app2.js"
}
let newEntries = {
//from entries should be that:
app: ["#babel/polyfill", "/main/application/src/app/src/pages/app/src/index.js"],
app1: ["#babel/polyfill", "/main/application/src/app/src/pages/app/src/app1.js"],
app2: ["#babel/polyfill", "/main/application/src/app/src/pages/app/src/app2.js"],
}
You can use .reduce with Object.entries to achieve this. Firstly, Object.entries will give you an array of key-value pairs within your entries object:
[["app", "/main/application/src/app/src/pages/app/src/index.js"], ...]
You can then use .reduce to build up a new object, which gets every inner array of the above array (ie: gets every key-value) and adds that to the new object. However, the value of the new object is instead an array with the current value with the string "#babel/polyfill".
See implemenation below:
let entries = {
"app": "/main/application/src/app/src/pages/app/src/index.js",
"app1": "/main/application/src/app/src/pages/app/src/app1.js",
"app2": "/main/application/src/app/src/pages/app/src/app2.js"
}
const arr_res = Object.entries(entries).reduce(
(acc, [k, v]) => ({...acc, [k]: ["#babel/polyfill", v]}),
{});
console.log(arr_res);
The following is a shortcut assuming "#babel/polyfill" is constant but that is easily changeable.
let entries = {
"app": "/main/application/src/app/src/pages/app/src/index.js",
"app1": "/main/application/src/app/src/pages/app/src/app1.js",
"app2": "/main/application/src/app/src/pages/app/src/app2.js"
};
let newEntries = Object.keys(entries).map(key => [key,["#babel/polyfill", entries[key]]])
.reduce((a,c) => {a[c[0]] = c[1]; return a},{});
console.log(newEntries);
If I remember correctly Object.entries() is more recent than Object.keys() so I will leave this here in case browser support matters.
I see you got a couple of poor answers (edit: later ones aren't poor) to this question. To prevent your being sent off in a random direction, you just loop through the properties creating an array with your hardcoded first entry and the property value as the second property. Here's an example using Object.fromEntries (quite new, but easily polyfilled) and Object.entries (somewhat new, but easily polyfilled):
let newEntries = Object.fromEntries(
Object.entries(entries).map(([key, value]) => [key, ["#babel/polyfill", value]])
);
Live Example:
let entries = {
"app": "/main/application/src/app/src/pages/app/src/index.js",
"app1": "/main/application/src/app/src/pages/app/src/app1.js",
"app2": "/main/application/src/app/src/pages/app/src/app2.js"
};
let newEntries = Object.fromEntries(
Object.entries(entries).map(([key, value]) => [key, ["#babel/polyfill", value]])
);
console.log(newEntries);
.as-console-wrapper {
max-height: 100% !important;
}
Or doing it manually rather than using those new-ish helpers:
let newEntries = {};
for (const key in entries) {
if (entries.hasOwnProperty(key)) {
newEntries[key] = ["#babel/polyfill", entries[key]];
}
}
Live Example:
let entries = {
"app": "/main/application/src/app/src/pages/app/src/index.js",
"app1": "/main/application/src/app/src/pages/app/src/app1.js",
"app2": "/main/application/src/app/src/pages/app/src/app2.js"
};
let newEntries = {};
for (const key in entries) {
if (entries.hasOwnProperty(key)) {
newEntries[key] = ["#babel/polyfill", entries[key]];
}
}
console.log(newEntries);
.as-console-wrapper {
max-height: 100% !important;
}

Categories