Create an array of values from object based on key - javascript

If I have an object
post = {
title: "Title",
image_1: "1234",
image_2: "2345"
}
and I want to get an array:
["1234", "2345"]
This is how I filter attributes to be included in the array
Object.keys(post).filter(key =>
key.includes("image")
);
and get an array of correct keys. How do I get values instead?

One way is to just do your filter then map the object lookup:
Object.keys(post)
.filter(key => key.includes("image"))
.map(key => post[key])
Or, use Object.entries to get both keys and values:
Object.entries(post)
.filter(([key, value]) => key.includes("image"))
.map(([key, value]) => value)
Or, with a "filter and map" operation:
Object.entries(post)
.flatMap(([key, value]) => key.includes("image") ? [value] : [])

You can use Object.entries to get a list of key-value pairs, and .forEach to iterate over it:
const post = {
title: "Title",
image_1: "1234",
image_2: "2345"
};
const res = [];
Object.entries(post).forEach(([key,value]) => {
if(key.includes("image")) res.push(value);
});
console.log(res);

const post = { title: "Title", image_1: "1234", image_2: "2345" };
const keys = Object.keys(post).filter(key => key.includes("image"));
const output = keys.map(key => post[key]);
console.log(output); // [ '1234', '2345' ]

You could use reduce method on Object.entries and check if the key startsWith a specific string.
const post = {
title: "Title",
image_1: "1234",
image_2: "2345"
}
const result = Object
.entries(post)
.reduce((r, [k, v]) => {
if (k.startsWith('image')) r.push(v);
return r;
}, [])
console.log(result)

Object.entries to obtain entries, then filter those which starts with image:
let post={title:"Title",image_1:"1234",image_2:"2345"};
let result = Object.entries(post)
.filter(e => e[0].startsWith('image'))
.flatMap(e => e[1])
console.log(result)

Related

how can swap the key and array of values, of an object in JavaScript?

This is my data:
obj = Object {
Great Lakes: Array(3) ["Michigan", "Indiana", "Ohio"]
Heartland: Array(2) ["Missouri", "Illinois"]
}
How can I change it to something like one by one:
{"Illinois": "Heartland", "Michigan": "Great Lakes", ...}
I have to use Map, Object.entries and Array.flat().
I used : namemap = new Map(Object.entries(obj).map(function ([k, v]) {return [v, k];} ))
but this is not I want or maybe this is not complete.
Your code is almost correct, you just need to iterate the values in each array in obj:
const obj = {
'Great Lakes': ["Michigan", "Indiana", "Ohio"],
'Heartland': ["Missouri", "Illinois"]
}
const namemap = new Map(
Object.entries(obj)
.map(([k, a]) => a.map(v => [v, k]))
.flat()
)
for (const [key, value] of namemap.entries()) {
console.log(`${key} : ${value}`);
}
You can try a combination of .reduce and .forEach to get the value you need
let data = {
'Great Lakes':["Michigan", "Indiana", "Ohio"],
'Heartland': ["Missouri", "Illinois"]
}
let result = Object
.entries(data)
.reduce((acc, [key, value]) =>
value.forEach((v) => acc[v] = key) || acc
, {})
console.log(result)

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));

Getting object data with key value in JavaScript

I have an object like this:
{
"idMeal": "52795",
"strMeal": "Chicken Handi",
"strDrinkAlternate": null,
"strCategory": "Chicken",
"strArea": "Indian"
}
I am trying to get the value of other items(i.e. strMeal and strCategory) using the value of "idMeal". How can I do that?
As far as i understood you want to filter an list of food objects, just put them in an array and filter like this:
[obj1, obj2, obj3].filter(o => o.idMeal="52795")
First you should have stated what you tried. Then, you can use a simple condition:
let cat;
let area;
if (obj.idMeal === myValue) {
cat = obj.strCategory;
area = obj.strArea;
}
There are way more ways of doing this. Take a look at .map(), .filter() but those are for arrays.
The easiest way to achieve this is to filter the data based on the key-value pair and then reduced the requested fields into a new object.
const mealData = [{
"idMeal": "52795",
"strMeal": "Chicken Handi",
"strDrinkAlternate": null,
"strCategory": "Chicken",
"strArea": "Indian",
}];
const filterAndMap = (data, key, value, fields) =>
data
.filter((record) => record[key] === value)
.map(record => fields.reduce((acc, field) =>
({ ...acc, [field]: record[field] }), {}));
const result = filterAndMap(mealData, 'idMeal', '52795', ['strMeal', 'strCategory']);
console.log(result);
Alternatively, you could pass a filter function and a mapper function:
const mealData = [{
"idMeal": "52795",
"strMeal": "Chicken Handi",
"strDrinkAlternate": null,
"strCategory": "Chicken",
"strArea": "Indian",
}];
const filterAndMap = (data, filterFn, mapperFn) =>
data.filter(filterFn).map(mapperFn);
const result = filterAndMap(
mealData,
({ idMeal }) => idMeal === '52795',
({ strMeal, strCategory }) => ({ strMeal, strCategory }));
console.log(result);
In the example above, we can remove the filterAndMap function and just chain filter and map directly.
const mealData = [{
"idMeal": "52795",
"strMeal": "Chicken Handi",
"strDrinkAlternate": null,
"strCategory": "Chicken",
"strArea": "Indian",
}];
const result = mealData
.filter(({ idMeal }) => idMeal === '52795')
.map(({ strMeal, strCategory }) => ({ strMeal, strCategory }));
console.log(result);

How can I generate a key pairing object result with lodash?

I have the following array:
const ids = ["1234", "5678", "0987", "6543"]
And I need a function with lodash that returns:
const result = {"1234": { workId: null }, "5678": { workId: null }, "0987": { workId: null }, "6543": { workId: null }}
What is the way using lodash methods?
Thanks for the help
Here's a lodash solution that uses lodash#invert and lodash#mapValues
const result = _(ids)
.invert()
.mapValues(() => ({ workId: null }))
.value();
const ids = ["1234", "5678", "0987", "6543"];
const result = _(ids)
.invert()
.mapValues(() => ({ workId: null }))
.value();
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Disclaimer: lodash is pretty overkill for that.
You can use reduce (link to doc)... or its plain JS equivalent.
const ids = ["1234", "5678", "0987", "6543"]
console.log(ids.reduce((acc, key) => Object.assign(acc, { [key]: { workId: null } }), {}));
Note that I use a feature of ES2015 to dynamically set the name of the new key to add to the accumulator.

Categories