I have an API that response JSON data like this-
{
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
}
I want to change like this-
{
"Value1":"apple",
"Value2":"bus",
"value3":"red",
"value4":"sale"
}
Presently, I can code to rename single key but i want some code to replace all key in one shot. my code like this-
request(baseurl)
.then( body => {
var unit = JSON.parse(body);
unit.intent = "sales"
unit.value1 = unit.unitcode
delete unit.unitcode;
console.log(unit)
console.log(unit.Value1)
var unit2 = JSON.stringify(unit)
// let code = unit.description;
conv.ask('Sales is 1 million metric tonnes ' + unit2);
})
please help me out on this and please little elaborate also to learn something new. thanks
Create a Map of original key to new key (transformMap). Convert the object to pairs of [key, value] with Object.entries(), iterate with Array.map() and replace the replacement key from the Map (or the original if not found). Convert back to an object with Object.toEntries():
const transformMap = new Map([
['unitcode', 'Value1'],
['description', 'Value2'],
['color', 'Value3'],
['intent', 'Value4']
]);
const transformKeys = obj =>
Object.fromEntries(
Object.entries(obj)
.map(([k, v]) => [transformMap.get(k) || k, v])
);
const obj = {
"unitcode": "apple",
"description": "bus",
"color": "red",
"intent": "Name 1"
};
const result = transformKeys(obj)
console.log(result)
If you know the object structure and it is constant, you could just use destructing like so.
const data = {
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
};
// If the object is fixed and the fields are known.
const mapData = ({ unitcode, description, color, intent }) => ({
Value1: unitcode,
Value2: description,
Value3: color,
Value4: intent
});
console.log(JSON.stringify(mapData(data)));
But if the object has an unknown number of properties:
const data = {
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
};
// If the object is fixed and the fields are known.
const mapData = (data) => {
return Object.keys(data).reduce((a,v,i) => {
a[`Value${i+1}`] = data[v];
return a;
}, {});
};
console.log(JSON.stringify(mapData(data)));
You can edit the array to have the values you need
let i=0,j=0,unit1={};
let unit = JSON.parse(body);
let unit3=["val1","val2","val3","val4"]
let unit5=Object.values(unit);
for(let key in unit){
unit1[unit3[i++]]=unit5[j++];
}
var unit2 = JSON.stringify(unit1)
console.log('Sales is 1 million metric tonnes \n' + unit2);
//Sales is 1 million metric tonnes
//{"val1":"apple","val2":"bus","val3":"red","val4":"Name 1"}
Well your target is to modify the keys and retain the value
In that context, you can iterate through your data. To dynamically generate keys as Value1, Value2, etc, we will append Value with iteration index which is going to be unique always.
const modifyInput = (input) => {
const modifiedInput = {}
Object.values(input).forEach((item, index) => {
modifiedInput[`Value${index + 1}`] = item
})
return modifiedInput
}
Use this function, pass your input and get your desired result
Related
I need convert this object:
{
"en": "[\"En1\",\"En2\"]",
"de": "[\"De1\",\"De2\"]"
}
to:
[
{
"en": "En1",
"de": "De1"
},
{
"en": "En2",
"de": "De2"
}
]
Can you help me?
i tried as follows:
const obj = {
en: '["En1","En2"]',
de: '["De1","De2"]',
};
const result = Object.entries(obj).map(([key, value]) => ({
[key]: JSON.parse(value),
}));
console.log(result)
but this only returns me an array of objects and I don't know how to go ahead and create a new array with key-value matches.
const data = {
"en": "[\"En1\",\"En2\"]",
"de": "[\"De1\",\"De2\"]"
}
console.log(Object.values(Object.entries(data).reduce((a,[k,v])=>
(JSON.parse(v).forEach((e,i)=>(a[i]??={})[k]=e),a),{})))
You can separate your object into 2 arrays then combine them like this
const obj = {
en: '["En1","En2"]',
de: '["De1","De2"]',
};
// Convert to array, separate them by key
let en = JSON.parse(obj.en.split(','));
let de = JSON.parse(obj.de.split(','));
//then combine both arrays
const result = en.map((x,i) =>({
en:x,
de:de[i]
}))
console.log(result);
You can use a combination of Array#map and Array#reduce as follows. The number of items is not hard-corded, so this will work for any number of items:
const
input = { "en": "[\"En1\",\"En2\"]", "de": "[\"De1\",\"De2\"]"},
output = Object.entries(input)
.map(([key,vals]) => JSON.parse(vals).map(v => ({[key]:v})))
//..producing [[{"en":"En1"},{"en":"En2"}],.....]
.reduce(
(obj, values) =>
obj.length === 0 ?
values.map(v => v) : //initial result: [{"en":"En1"},{"en":"En2"}]
values.map((v,i) => ({...obj[i],...v})), //appends "de" prop to each element, ....
[]
);
console.log( output );
I've opted for a more imperative approach here. It appends objects to the returnArray array for each index of the parsed values array. If value matches idx + 1 (eg 'De1'.includes(1)), a key-value pair is initialized on the object at the current index of the returnArray array.
My answer relies on a lot of assumptions regarding the input. If the parsed string array elements are not in numerical order, or there are gaps in the values, eg De3, De1, De2, or De1, De6, the current solution doesn't account for it.
let returnArray = [];
Object.entries(obj).forEach(pair => {
let key = pair[0];
let values = JSON.parse(pair[1]);
values.forEach((_el, idx) => {
if (!returnArray[idx]) {
returnArray.push({});
}
let value = values[idx];
if (value.includes(idx + 1)) {
returnArray[idx][key] = values[idx];
}
});
});
I have a array of objects, for exemple:
let arr = [
{title:apple,quantity:2},
{title:banana,quantity:3},
{title:apple,quantity:5},
{title:banana,quantity:7}
];
array containe many same objects, and i want recived array with uniqe object :
let result = [
{title:apple,quantity:7},
{title:banana,quantity:10}
]
How can I do this?
You can iterate over your array and filter out all the object with same title. Then use reduce to add all the quantity and return a new object. Code is below,
let newArr = [];
arr.forEach((currentObj) => {
const alreadyExists = newArr.findIndex(item => currentObj.title === item.title) > -1;
if(!alreadyExists) {
const filtered = arr.filter(item => item.title === currentObj.title);
const newObject = filtered.reduce((acc, curr) => { return {...acc, quantity: acc.quantity += curr.quantity}}, {...currentObj, quantity: 0})
newArr.push(newObject);
}
})
console.log(newArr);
This is done on a phone so may have some typos but the gist is there:
const resultObj = arr.reduce((acc,curr) =>{
acc[curr.title] = acc[curr.title]== undefined? curr.quantity: acc[curr.title] + curr.quantity
return acc
},{})
const resultArr = Object.entries(resultObj).map([key,value]=>({title:key,quantity:value}))
You could do that in "one line" using arrow function expressions but it won't be very readable unless you know what's happening inside:
let arr = [
{title: "apple",quantity:2},
{title: "banana",quantity:3},
{title: "apple",quantity:5},
{title: "banana",quantity:7}
];
let newArr = [...arr.reduce((acc, {title, quantity}) =>
(acc.set(title, quantity + acc.get(title) || 0), acc), new Map())
].map(([title, quantity]) => ({title, quantity}));
console.log(newArr);
So basically the first part is the reduce method:
arr.reduce((acc, {title, quantity}) =>
(acc.set(title, quantity + acc.get(title) || 0), acc), new Map())
That will returns a Map object, where each title is a key (e.g. "apple") and the quantity is the value of the key.
At this point you have to convert the Map object into an array again, and you do it using the spread syntax.
After you got an array back, you will have it in the following form:
[["apple", 7], ["banana", 10]]
But that is not what you want yet, not in this form, so you have to convert it using the array's map method:
<array>.map(([title, quantity]) => ({title, quantity}))
To keep it concise it uses the destructuring assignment
I have two object arrays. I want to merge with key with value
var a = [{"fit":["34","32","30","28"],"size":["x"]}]
var b = [{"size":["s","m","xl"],"fit":["36"]}]
Expected Output should be
Obj=[{"fit":["34","32","30","28","36"],"size":["x,"s","m","xl"]}]
My Code is
let arr3 = [];
b.forEach((itm, i) => {
arr3.push(Object.assign({}, itm, a[i]));
});
alert(JSON.stringify(arr3))
it gives [{"size":["x"],"fit":["34","32","30","28"]}] which wrong.
Use Array.reduce().
// Combine into single array (spread operator makes this nice)
const myArray = [...a, ...b];
// "reduce" values in array down to a single object
const reducedArray = myArray.reduce((acc, val) => {
return [{fit: [...acc.fit, ...val.fit], size: [...acc.size, ...val.size]}];
});
Edit: if you want the reducer to merge objects regardless of what keys and fields it has then you can do by iterating over the keys of the objects and merging them dynamically:
const reducedArray = myArray.reduce((acc, val) => {
const returnObject = {};
for (const eaKey in acc) {
returnObject[eaKey] = [...acc[eaKey], ...val[eaKey]];
}
return [returnObject];
});
If the fields of the objects aren't guaranteed keys then you will need to get even more dynamic in detecting the type of merge and how to do it, but it's possible and I will leave that as an exercise for you to figure out. :)
Note that if there are duplicate values in each of the "fit" and "size" arrays, they will not be deduplicated. You'd have to do that manually as a separate step either with extra logic in the reduce function or afterwards.
combine a and b in a single array then reduce it starting with an array having an object with empty fit and size arrays:
var a = [{ fit: ["34", "32", "30", "28"], size: ["x"] }];
var b = [{ size: ["s", "m", "xl"], fit: ["36"] }];
var obj = [...a, ...b].reduce(
(acc, curr) => {
Object.keys(curr).forEach(k => {
acc[0][k] = [...new Set([...(acc[0][k] || []), ...curr[k]])];
});
return acc;
},
[{}]
);
console.log(obj);
You can create a combine function that takes fit and size from any two objects and merges them.
Use it as a reducer to combine everything.
let combine = ({fit, size}, {fit: fit2, size: size2}) =>
({ fit: [...fit, ...fit2], size: [...size, ...size2] });
let result = [...a, ...b].reduce(combine);
Example:
var a = [{"fit":["34","32","30","28"],"size":["x"]}, {"fit": ["10", "11"], "size":["xxxxxxxxl"]}]
var b = [{"size":["s","m","xl"],"fit":["36"]}];
let combine = ({fit, size}, {fit: fit2, size: size2}) =>
({ fit: [...fit, ...fit2], size: [...size, ...size2] });
let result = [...a, ...b].reduce(combine);
console.log(result);
If you don't want to use the keys directly you could try
const arr3 = b.reduce((carry, current, index) => {
Object.keys(current)
.forEach(key => {
Object.assign(carry, { [key]: Array.prototype.concat.call(current[key], a[index][key])});
});
return carry;
}, {});
I am building an typescirpt dictionary like that:
const skills = x
.map(y => y.skills)
.flat(1)
.map(z => {
return { [z.id]: { skill: z } };
});
That is the array I am getting by the code above:
{ 7ff2c668-0e86-418a-a962-4958262ee337: {skill: {…}} }
{ c6846331-2e11-45d6-ab8d-306c956332fc: {skill: {…}} }
{ 0fc0cb61-f44d-4fd0-afd1-18506380b55e: {skill: {…}} }
{ 36dc0b74-84ee-4be2-a91c-0a91b4576a21: {skill: {…}} }
Now the issue is I can not access the dictionary by key:
const id = '7ff2c668-0e86-418a-a962-4958262ee337';
const one = myArr.find(x => x === id); // returns undefined
const two = myArr[id]; // returns undefined
Any ideas how to fix?
You can use Object.keys() to get the key of each of your objects. In your case the key of each of your objects is its id. Then use that to check whether it equals x (you search id).
See example below:
const myArr = [
{"7ff2c668-0e86-418a-a962-4958262ee337": {skill: 1}},
{"c6846331-2e11-45d6-ab8d-306c956332fc": {skill: 2}},
{"0fc0cb61-f44d-4fd0-afd1-18506380b55e": {skill: 3}},
{"36dc0b74-84ee-4be2-a91c-0a91b4576a21": {skill: 4}}],
id = "36dc0b74-84ee-4be2-a91c-0a91b4576a21",
one = myArr.findIndex(x => Object.keys(x)[0] === id); // the index of the object which has the search id as its key.
myArr[one] = {newKey: "newValue"}; // set the index found to have a new object
console.log(myArr);
You are now creating an array of objects. I suggest you create an object instead, with your ids as keys
Example:
const skills = x
.map(y => y.skills)
.flat(1)
.reduce((acc, z) => {
acc[z.id] = z;
return acc;
}, {});
Your myArr is going to look something like:
{
'7ff2c668-0e86-418a-a962-4958262ee337': {...}
'c6846331-2e11-45d6-ab8d-306c956332fc': {...},
'0fc0cb61-f44d-4fd0-afd1-18506380b55e': {...},
'36dc0b74-84ee-4be2-a91c-0a91b4576a21': {...}
}
You can then access it the way you intended:
const skill = myArr['7ff2c668-0e86-418a-a962-4958262ee337'];
make use of map that can help,
Map is a new data structure introduced in ES6. It allows you store key-value pairs similar to other programming languages e.g. Java, C#.
let map = new Map();
const skills = x
.map(y => y.skills)
.flat(1)
.map(z => {
map.set(z.Id, { skill: z })
return map;
});
//Get entries
amp.get("7ff2c668-0e86-418a-a962-4958262ee337"); //40
//Check entry is present or not
map.has("7ff2c668-0e86-418a-a962-4958262ee337"); //true
Creating an array based off selected DataTables Rows
$('#savenlp').click(recordjourney);
function recordjourney() {
var data = table.rows(['.selected']).data().toArray();
console.log( (data) );
console.log( JSON.stringify(data) );
}
data returns
0 : (8) ["Which", "TitleCase", "QuestionWord", "", "", "", "", ""]
JSON.stringify(data) returns
[["baseball","Noun","Singular","","","","",""]]
This information is dynamically generated, so I am just looking to take the first value (in this case baseball) and turn it into something like
"baseball": [
"Noun",
"Singular"
]
I can return the first value (the key I want using)
alert(data[0][0]);
I am much more adept in PHP but I am learning javascript/jquery more and more.
It is my understanding javascript does not have associative arrays, so I am a bit confused as to how to generate this.
const data = [
["baseball","Noun","Singular","","","","",""],
["baseballs","Noun","","Plural","","","","",]
];
const mappedData = data.reduce((acc, row) => { acc[row.shift()] = row.filter(d => d !== ''); return acc; }, {});
console.log(mappedData);
We can use object destructuring and spread operators for ease of use.
In the example below, the key will be the first item and all the rest items will be placed in the newData variable
const data = [["baseball","Noun","Singular","","","","",""]];
const [key, ...newData] = data[0]
// if you want the new data to not have empty entries, simple apply the filter
const newDataFiltered = newData.filter(item => !!item)
const objWithEmpty = {[key]: newData}
const objWithoutEmpty = {[key]: newDataFiltered}
console.log(objWithEmpty, objWithoutEmpty)
For multiple arrays inside the outer array, just enclose the whole logic inside a for loop
const data = [
["baseball","Noun","Singular","","","","",""],
["baseball1","Noun1","Singular1","","","","",""],
["baseball2","Noun2","Singular2","","","","",""]
];
const objWithEmpty = {}
const objWithoutEmpty = {}
data.forEach((array) => {
const [key, ...newData] = array
// if you want the new data to not have empty entries, simple apply the filter
const newDataFiltered = newData.filter(item => !!item)
objWithEmpty[key] = newData
objWithoutEmpty[key] = newDataFiltered
})
console.log(objWithEmpty, objWithoutEmpty)
Simply extract the desired values from data and put them into an object formatted as you like:
const data = [["baseball","Noun","Singular","","","","",""]];
const firstArr = data[0];
const transformedFirstObject = {
[firstArr[0]]: [firstArr[1], firstArr[2]],
};
console.log(transformedFirstObject);
But it's pretty weird to have an object with only one property like that. If your data might have more than one sub-array in it and you want to turn the array of arrays into an array of objects, use map:
const data = [
["baseball","Noun","Singular","","","","",""],
["foo","bar","baz","","","","",""]
];
const transformed = Object.assign(...data.map(([prop, value1, value2]) => ({ [prop]: [value1, value2] })));
console.log(transformed);
A bit simpler compared to other answers here but works as well.
const data = [
["baseball","Noun","Singular","","","","",""],
["baseball1","Noun1","Singular1","","","","",""],
["baseball2","Noun2","Singular2","","","","",""]
];
const obj = [];
data.forEach(function(i) {
let jsonObj = {};
jsonObj [i[0]] = i.slice(1).filter(x=>x !='');
obj.push(jsonObj)
});
console.log(JSON.stringify(obj))
Just using forEach, considering multiple array elements.
var obj = {};
var arr = [
["baseball", "Noun", "Singular", "", "", "", "", ""],
["Test", "Test1", "Test2", "", "", "", "", ""]
];
arr.forEach(function(val, idx) {
val.forEach(function(val1, idx1) {
if (idx1 === 0) {
obj[val1] = val.slice(1, val.length)
}
})
})
console.log(JSON.stringify(obj))