Convert array of objects to an object - javascript

I have created this function, however is not quite right. I get this response from it:
[
{
manufacturer: [
'AUDI'
]
},
{
body_colour: {
'BLACK'
}
}
]
However what I want is:
{
manufacturer: [
'AUDI'
],
body_colour: {
'BLACK'
}
}
How can I get to this? This is what I have at the moment:
checkForQueryString() {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
let searchParams = Object.entries(params).map(([key, value]) => {
return {
[key]: value.split(',')
}
});
return searchParams;
},
Query String: ?manufacturer=AUDI&body_colour=BLACK

Use reduce not map
const params = {
manufacturer: "AUDI",
body_colour: "BLACK"
}
let searchParams = Object.entries(params).reduce((acc, [key, value]) => {
return {
...acc,
[key]: value.split(',')
}
}, {});
console.log(searchParams)

Object.fromEntries(urlSearchParams.entries()), Object.entries(params) are not necessary.
You can use a simple forEach function to achieve the desired result as from MDN DOCS.
function checkForQueryString() {
const searchParams = new URLSearchParams(window.location.search);
var result = {};
searchParams.forEach(function(value, key) {
result[key] = value.split(',');
});
return result;
}
console.log( checkForQueryString() );
When url is http:example.com?manufacturer=audi,tesla&body_colour=black,white
the output would be
{
"manufacturer": [
"audi",
"tesla"
],
"body_colour": [
"black",
"white"
]
}

Assumin you meant by your input:
body_colour: [
'BLACK'
]
The answer can be:
let myArray = [
{
manufacturer: ['AUDI']
},
{
body_colour: ['BLACK']
}
];
let newObj = Object.assign({}, ...myArray)

You can make use of Object.fromEntries with split and map:
const str = 'manufacturer=AUDI&body_colour=BLACK';
console.log(Object.fromEntries(str.split('&').map(o=>[o.split('=')[0],[o.split('=')[1]]])));

Related

JavaScript Array attribute change

I have an array like this.
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
I want to change it to like this
let me explain it a little. I want to assign the abbreviation directly to the name and the iterate through that array
let outout = [
{
"ISB":"ISLAMABAD"
},
{
"RAW":"ISLAMABAD"
},
{
"SWB":"SWABI"
},
{
"AQ":"AQEEL"
},
]
that is what I tried
let k = arr.map((item) => {
return item.ABB = item.name
})
console.log(k)
and here is the output
[ 'ISLAMABAD', 'PINDI', 'SWABI', 'AQEEL' ]
Here you go, use array map, simples
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
let outout = arr.map(({ABBRIVATION, name}) => ({[ABBRIVATION]: name}));
console.log(outout);
Nothing more than a simple Array.prototype.map() needed.
let arr = [
{
ABBRIVATION: "ISB",
name: "ISLAMABAD",
},
{
ABBRIVATION: "RAW",
name: "PINDI",
},
{
ABBRIVATION: "SWB",
name: "SWABI",
},
{
ABBRIVATION: "AQ",
name: "AQEEL",
},
];
const result = arr.map(e => ({ [e.ABBRIVATION]: e.name }));
console.log(result);
map over the array of objects (map returns a new array) and assign the name to a new key defined by the abbreviation.
You code works the way it does because item.ABB is undefined, but you're also assigning item.name to it which does get returned, so you just get an array of names returned.
const arr=[{ABBRIVATION:"ISB",name:"ISLAMABAD"},{ABBRIVATION:"RAW",name:"PINDI"},{ABBRIVATION:"SWB",name:"SWABI"},{ABBRIVATION:"AQ",name:"AQEEL"}];
const out = arr.map(obj => {
return { [obj.ABBRIVATION]: obj.name };
});
console.log(out);
Hi I have seen people answer, but most of them use the map function, I provide some other solutions, hoping to expand the thinking
Use forEach function
const datas = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
}
];
datas.forEach((obj, i, arr) => {
const{'ABBRIVATION':k, 'name':v} = obj;
arr[i] = {[k]:v};
});
console.log(datas);
Use flatMap function
const datas = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
}
];
const result = datas.flatMap(obj => {
const {'ABBRIVATION':k, 'name':v} = obj;
return {[k]:v};
});
console.log(result);
this is how you suppose to do it.
arr.reduce((d, c)=>([...d, {[c.ABBRIVATION]: c.name}]),[])
let arr = [
{
"ABBRIVATION":"ISB",
"name":"ISLAMABAD",
},
{
"ABBRIVATION":"RAW",
"name":"PINDI",
},
{
"ABBRIVATION":"SWB",
"name":"SWABI",
},
{
"ABBRIVATION":"AQ",
"name":"AQEEL",
},
]
console.log(arr.reduce((data, current)=>([...data, {[current.ABBRIVATION]: current.name}]),[]))

How to filter in two deep arrays

I'm looking to filter in two deep arrays, actually my JSON:
{
"0": {
"product":[{
"uuid":"uid",
"name":"Rice"
},
{
"uuid":"uid",
"name":"Pasta"
}]
},
"1": {
"product":[{
"uuid":"uid",
"name":"Milk"
}]
}
}
I would like to get something like that when I filter with the word "ric":
{
"0": {
"product":[{
"uuid":"uid",
"name":"Rice"
}]
}
}
But I got this result:
{
"0": {
"product":[{
"uuid":"uid",
"name":"Rice"
},
{
"uuid":"uid",
"name":"Pasta"
}]
}
}
My code:
dataSort.categories = the json and
event.target.value.toLowerCase() = the specific word
dataSort.categories.filter(s => s.products.find(p => p.name.toLowerCase().includes(event.target.value.toLowerCase())));
You can achieve this with a combination of reduce and filter
var input = {
"0": {
"product":[{
"uuid":"uid",
"name":"Rice"
},
{
"uuid":"uid",
"name":"Pasta"
}]
},
"1": {
"product":[{
"uuid":"uid",
"name":"Milk"
}]
}
}
var search = "ric"
var result = Object.entries(input).reduce( (acc, [key,val]) => {
found = val.product.filter(x => x.name.toLowerCase().includes(search.toLowerCase()))
if(found.length){
acc[key] = {...val, product: found}
}
return acc
},{})
console.log(result)
There is many approach to do this, one is to map your top level array to the subArrays filtered results then filter it after:
dataSort.categories
.map(s => s.products.filter(p => p.name.toLowerCase().includes(event.target.value.toLowerCase())))
.filter(s => !!s.products.length);
You may also prefer to get a "flat" array as result because it is easier to use after :
dataSort.categories
.reduce((acc, s) => [...acc, s.products.filter(p => p.name.toLowerCase().includes(event.target.value.toLowerCase()))], []);
Please find below the code to filter out values inside the product.name and only return the value which are matching the equality condition in product array.
const json = [
{
product: [
{
uuid: "uid",
name: "Rice",
},
{
uuid: "uid",
name: "Pasta",
},
],
},
{
product: [
{
uuid: "uid",
name: "Milk",
},
],
},
];
const inputValue = "rIc";
const filteredArray = [];
json.map((s) => {
const item = s.product.find((p) =>
p.name.toLowerCase().includes(inputValue.toLowerCase())
);
item && filteredArray.push({ product: item });
});
console.dir(filteredArray);
Your dataset is an Object, not an Array and the filter is an Array method. You can use reduce by looping on the object values by Object.values then filter your products array.
const data = {
'0': {
product: [
{
uuid: 'uid',
name: 'Rice',
},
{
uuid: 'uid',
name: 'Pasta',
},
],
},
'1': {
product: [
{
uuid: 'uid',
name: 'Milk',
},
],
},
};
const keyword = 'ric';
const dataset = Object.values(data);
const results = dataset.reduce((acc, item, index) => {
const search = keyword.toLowerCase();
const product = item.product.filter(product => product.name.toLowerCase().includes(search));
if (product.length) acc[index] = { ...item, product };
return acc;
}, {});
console.log(results);

How to convert object key value pair with array as values to multi objects of key value pair?

I have an object with key-value pair and its value as an array of elements.
{
status: ["new", "old"],
place: ["york", "blah"]
}
I'm trying to convert it into multiple array objects of key-value pair like below.
{
"newObj1": [
{ "status": "new" },
{ "status": "old" }],
"newObj2": [
{ "place": "york" },
{ "place": "blah" }]
}
Is there any way to achieve the above structure? I have tried couple of methods using array reduce methods but it doesn't give in the desired output.
let value= {
status: ["new", "old"],
place: ["york", "blah"]
}
Object.keys(value).map((key) => [key, value[key]]);
You can do something like this
const obj = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = {};
Object.keys(obj).forEach((key, index) => {
result[`newObj${index + 1}`] = obj[key].map(item => ({[key]: item}));
});
console.log(result);
Here's a solution that uses Array.reduce():
const value = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = Object.keys(value).reduce((acc, key, i) => {
acc["newObj" + (i + 1)] = value[key].map(k => ({ [key]: k }));
return acc;
}, {});
console.log(result);
Here is my way of accomplishing that.
let source = {
status: ["new", "old"],
place: ["york", "blah"]
};
let destination = {}; // make room for the destinoation object
Object.keys(source).forEach((key, index) => {
let obj = "newObj" + (index + 1); // assume all objects are named "newObj1,2,3,etc"
if (!destination[obj]) { // check if the object exists already
// if not, then crate an empty array first
destination[obj] = [];
}
// loop through all items in the source element array
source[key].forEach(value => {
// create an object from the array element
let subObj = {};
subObj[key] = value;
// push that object to the destination
destination[obj].push(subObj);
});
});
console.log(destination);
const data = {
status: ["new", "old"],
place: ["york", "blah"]
};
let result = Object.fromEntries( Object.entries(data).map( ([key, [first, second]], index) => {
return [ `newObj${index}`, [ { [key]: first }, { [key]: second } ] ];
} ) );
console.log(result);
Here's an idiomatic solution using .reduce inside .reduce:
Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
Here's a live example:
const data = {
status: ['new', 'old'],
place: ['york', 'blah']
};
const result = Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
console.log(result);
/*
{
newObj1: [
{ status: 'new' },
{ status: 'old' }
],
newObj2: [
{ place: 'york' },
{ place: 'blah' }
]
}
*/
For those who fail to understand map and reduce, here's a fairly naive solution but it will work:
newObjCounter = 1
orig = { status: [ 'new', 'old' ], place: [ 'york', 'blah' ] }
newObject = {}
//Initialise object with new keys with arrays as values
for(var key in orig){
newObject["newObj"+initialCounter] = []
initialCounter++
}
//Loop through keys of the original object and dynamically populate the new object
for(var key in orig){
index = "newObj"+objCounter
newObject[index].push({[key]:orig[key]})
objCounter++
}
console.log(newObject)

How to make json tree through group by json data?

Please take a look at my current json.
[
{"mode": "AR","fname": "ta","lname":"da","w_lng":"2.xx","w_lat":"1.xx"....},
{"mode": "AR","fname": "ta","lname":"da","w_lng":"3.xx","w_lat": "4.xx"....},
{"mode": "AR","fname": "ka","lname":"ja","w_lng":"6.xx","w_lat": "5.xx"....}
]
Now What I am looking for:
{
"mode": "AR",
"results": [
{
"fname": "ta",
"lname": "da",
"w_level": [
{ "w_lng": "2.xx",
"w_lat": "1.xx"
"anothelevel":[........]
},
{"w_lng": "3.xx",
"w_lat": "4.xx"
"anothelevel":[........]
}
]
}
{
"fname": "ka",
"lname": "ja",
"w_level": [
{
"w_lng": "x.xx",
"w_lat": "x.xx"
.....................
}
]
}
]
}
It is same as we do in SQL group by. suppose First group by world, then country, then city, then village etc. I was tried through group by. but the result is not my expected output. Please suggest me what should I do.
objMap = {};
for (let temp of obj) {
if (!objMap[temp.mode]) {
objMap[temp.mode] = { mode: temp.mode, results: [] }
}
let tempObj = { w_level: [], fname: temp.fname, lname: temp.lname };
let w_level = {};
for (let key of Object.keys(temp)) {
if (key !== "fname" && key !== 'lname' && key !== 'mode') {
w_level[key] = temp[key];
}
}
tempObj.w_level.push(w_level)
objMap[temp.mode].results.push(tempObj)
}
NOTE:get object by using Object.values(objMap);
Solution using reduce:
const inArr = [{"mode":"AR","fname":"Kiran","lname":"Dash","w_lng": "1.23", "w_lat": "2.23"},{"mode":"AR1","fname":"Suman","lname":"Dash","w_lng": "3.23", "w_lat": "4.23"},{"mode":"AR","fname":"Raman","lname":"Dash","w_lng": "5.23", "w_lat": "6.23"},{"mode":"AR","fname":"Milan","lname":"Dash","w_lng": "7.23", "w_lat": "8.23"},{"mode":"AR1","fname":"Naman","lname":"Dash","w_lng": "8.23", "w_lat": "9.23"},{"mode":"AR2","fname":"Phulan","lname":"Dash","w_lng": "10.23", "w_lat": "11.23"}]
console.log(
Object.values(inArr.reduce((item, currItem) => {
var { mode, fname, lname } = currItem;
if (!item[mode]) item[mode] = { mode, results: [] };
let w_level = {};
for (let key of Object.keys(currItem)) {
if (key !== "fname" && key !== 'lname' && key !== 'mode') {
w_level[key] = currItem[key];
}
}
item[mode].results.push({fname: fname, lname: lname, w_level: [w_level]});
return item;
}, {}))
);
Code walk through:
Loop over the input array, and group into an object indexed by mode.
Create an object with a result array if the mode doesn't exist yet, and push to that array.
Note: For the sake of simplicity, I have done it to one level. Please use the same approach to create multiple levels if you want.
------At last I found solution-----------
const reduceArrayByKeys = (inArr, keys, restKey) => {
const reduced = inArr.reduce((prev, cur) => {
const copied = { ...cur }
keys.forEach(key => delete copied[key])
const existing = prev.find(item => keys.every(key => item[key] === cur[key]))
if (existing) {
existing[restKey].push(copied)
} else {
const newItem = {}
keys.forEach(key => newItem[key] = cur[key])
newItem[restKey] = [copied]
prev.push(newItem)
}
return prev
}, [])
return reduced
}
const reduced = reduceArrayByKeys(inArr, ['mode'], 'results')
reduced.forEach(item => {
const results = item.results
item.results = reduceArrayByKeys(results, ['fname', 'lname'], 'w_level')
item.results.forEach(child => {
child.w_level = reduceArrayByKeys(child.w_level, ['w_lng', 'w_lat'],
'other')
})
})

Remove parent object and child object if value is undefined using Array.filter(?)

Question:
How can I removal all emailAddress that are empty, and if there are no emailAddresses for an approval, remove that approval too.
My current solution will remove approvals when emailAddress completely empty. But not when two emailAddresses are present and one is empty (see script output vs. expected output)
var request = {
approvals: [
{
type: 'media',
emailAddresses: [
{emailAddress: 'frank#gmail.com'},
]
},
{
type: 'other',
emailAddresses: [
{emailAddress: ''},
]
},
{
type: 'scope',
emailAddresses: [
{emailAddress: 'kelly#yahoo.com'},
{emailAddress: ''},
]
}
]
}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
let output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
// EXPECTED OUTPUT:
// approval: [
// {
// type: 'media',
// emailAddresses: [
// {emailAddress: 'frank#gmail.com'},
// ]
// },
// {
// type: 'scope',
// emailAddresses: [
// {emailAddress: 'kelly#yahoo.com'},
// ]
// }
// ]
// }]
Live Code
You are not replacing approval.emailAddresses in your code - you should use:
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
See demo below:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var filterOutEmptyEmails = (approval) => {
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
if(approval.emailAddresses.length){
return true;
}
}
var output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
EDIT:
Another proposal without mutating the input array - using Array.prototype.reduce to create a new array:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var output = request.approvals.reduce(function(p,c){
// creates a shallow copy
var elem = Object.assign({},c);
// replaces the reference to request.approvals by the new array created by the filter
elem.emailAddresses = elem.emailAddresses.filter(x => !!x.emailAddress);
if(elem.emailAddresses.length != 0)
p.push(elem);
return p;
},[]);
// console.log(request.approvals);
console.log(output);
.as-console-wrapper{top:0;max-height:100%!important;}
Possible "non mutation" solution could be like this
var request = {approvals: [{type: 'media',emailAddresses: [{emailAddress: 'frank#gmail.com'},]},{type: 'other',emailAddresses: [{emailAddress: ''},]},{type: 'scope', emailAddresses: [{emailAddress: 'kelly#yahoo.com'},{emailAddress: ''},]}]}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
const output = request.approvals.map(approval => {
const filteredAproval = approval;
filteredAproval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
return filteredAproval
}).filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
console.log(JSON.stringify(request));
Without mutation (with lots of ES6/7 sugar):
const filteredApprovals = request.approvals.reduce((acc, approval) => {
const filteredEmailAddresses = approval.emailAddresses.filter(item => item.emailAddress);
return (filteredEmailAddresses.length > 0) ? [...acc, { ...approval, emailAddresses: filteredEmailAddresses }] : acc;
}, []);
Fiddle: https://jsfiddle.net/free_soul/hndjbce3/

Categories

Resources