Changing arrays using map in javascript - javascript

This is my json object:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
I want my output like this:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"cats": [1,2] // this 1 and 2 is coming from categoriesservices array inside the category object i have id
}
How to do this using map function? I am new to javascript, which is good approach map or forloop?

See destructuring assignment, Array.prototype.map(), and JSON for more info.
// Input.
const input = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
// Categories => Objects to Cats => Ids.
const output = (input) => JSON.parse(JSON.stringify({
...input,
cats: input.categoryservices.map(({category: {id}}) => id),
categoryservices: undefined
}))
// Log.
console.log(output(input))

If you are not worried about original object immutability, then try this
obj['cats'] = obj['categoryservices'].map(cat => cat.category.id);
delete obj['categoryservices'];
console.log(obj);

I just use .map() on categoryservices array:
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map((element) =>
element.category.id);
delete output.categoryservices;
console.log(JSON.stringify(output));

use .map() , it return value as array ! You want to change is categoryservices key only ! So delete that after you get wanted value ..
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map(i => i.category.id );
delete output.categoryservices;
console.log(output);

Try this working demo :
var jsonObj = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
var arr = jsonObj.categoryservices.map(item => item.category.id)
jsonObj.cats = arr;
delete jsonObj.categoryservices;
console.log(jsonObj);

Try this
var testData={
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
testData.cats=[];
testData.categoryservices.forEach(function (item) {
testData.cats.push(item.category.id);
});
delete testData.categoryservices;
console.log(testData);

You can try using jquery each:
<div id="log"></div>
var conversation = {
'John': {
1: 'Test message 1',
2: 'Test message 2',
'Reply': {
3: 'Test message 3',
4: 'Test message 4'
}
},
'Jack': {
5: 'Test message 5',
6: 'Test message 6'
}
};
function iterate(obj) {
if (typeof obj === 'string') {
$('#log').append((obj + '<br/>'));
}
if (typeof obj === 'object') {
$.each(obj, function(key, value) {
iterate(value);
});
}
}
iterate(conversation);

Related

How to check if value is in an array with objects based on another array

In javascript I'm trying to check if value myPointID from b is in a.
I've tried:
console.log(a.points.filter((f) => f.myPoint.myPointID === b.myPointID));
I can't seem to figure out the correct way.
var a = [
{
"id": "1",
"name": "sample1",
"points": [
{
"pointID": "12",
"name": "sample point",
"myPoint": {
"myPointID": "12345",
"name": "sample my point",
"form": "form1"
}
}
]
},
{
"id": "2",
"name": "sample2",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
},
{
"id": "3",
"name": "sample3",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
}
];
var b = [
{myPointID: "123456", desc: "sm"},
{myPointID: "123456", desc: "sm2"}
];
You could take the wanted id from the filter array and check the data with a nested loop.
const
data = [{ id: "1", name: "sample1", points: [{ pointID: "12", name: "sample point", myPoint: { myPointID: "12345", name: "sample my point", form: "form1" } }] }, { id: "2", name: "sample2", points: [{ pointID: "123", name: "sample point2", myPoint: { myPointID: "123456", name: "sample my point2", form: "form2" } }] }, { id: "3", name: "sample3", points: [{ pointID: "123", name: "sample point2", myPoint: { myPointID: "123456", name: "sample my point2", form: "form2" } }] }],
filter = [{ myPointID: "123456", desc: "sm" }, { myPointID: "123456", desc: "sm2" }],
ids = new Set(filter.map(({ myPointID }) => myPointID));
console.log(data.filter(({ points }) =>
points.some(({ myPoint: { myPointID } }) => ids.has(myPointID))
));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This returns true or false for whether any myPointID from b exists in a using Array.prototype.reduce()
let b_myPointIds = b.map(function(x){ return x.myPointID})
let reducer = function(accumulator, aChild){ // 'value' is an array item from a
if (accumulator) { // if prev iteration returned true then shortcircuit
return accumulator;
}
for(let i = 0; i<aChild.points.length; ++i){
if(b_myPointIds.includes(aChild.points[i].myPoint.myPointID)){
return true;
}
}
return false;
}
let isMyPointIdInA = a.reduce(reducer, false); // false is initial value of 'isMyPointIdInA'
console.log(isMyPointIdInA);
var a = [
{
"id": "1",
"name": "sample1",
"points": [
{
"pointID": "12",
"name": "sample point",
"myPoint": {
"myPointID": "12345",
"name": "sample my point",
"form": "form1"
}
}
]
},
{
"id": "2",
"name": "sample2",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
},
{
"id": "3",
"name": "sample3",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
}
];
var b = [
{myPointID: "123456", desc: "sm"},
{myPointID: "123456", desc: "sm2"}
];
//--------------------------------------------------------------------------
let b_myPointIds = b.map(function(x){ return x.myPointID})
let reducer = function(accumulator, aChild){ // 'value' is an array item from a
if (accumulator) { // if prev iteration returned true then shortcircuit
return accumulator;
}
for(let i = 0; i<aChild.points.length; ++i){
if(b_myPointIds.includes(aChild.points[i].myPoint.myPointID)){
return true; // set accumulator to true
}
}
return false;
}
let isMyPointIdInA = a.reduce(reducer, false); // false is initial value of 'isMyPointIdInA'
console.log(isMyPointIdInA);

Parse Nested Level Json In javascript

Sample Input:
[
{
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": "special"
},
{
"id": "p2",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p3"},
{"key": "0", "value": "p4"},
{"key": "2", "value": "p5"}
],
"Next": "",
"RepeatText": "p8",
"RepeatTextNew": "p9",
},
{
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
},
{
"id": "p4",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p6"},
{"key": "0", "value": "p7"}
]
},
{
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
},
{
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
},
{
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
},
{
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
},
{
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
]
Sample Output:
{
"test1": {
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": {
"special": {
"id": "p2",
"Key": "special",
"Next": "",
"RepeatText": {
"p8": {
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
}
},
"RepeatTextNew": {
"p9": {
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
},
"specialkey": [
{
"key": "1",
"value": {
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p4",
"Key": "special",
"specialkey": [
{
"key": "1",
"value": {
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
}
}
]
}
},
{
"key": "2",
"value": {
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
}
}
]
}
}
}
}
When the key is equal to special it can have a nested structure and for either we just need to match with the next key
With the below code, I am not able to achieve the expected output.
const processObject = ({ Next, ...rest }) => {
const result = { ...rest };
if (formatData.find((y) => y.Key == 'special')) {
const nextObject = formatData.find((y) => y.Key == 'special')
if (nextObject.specialkey) {
for (let i = 0; i < nextObject.specialkey.length; i++) {
let currentObject = formatData.find((y) => y.id === nextObject.specialkey[i].value)
nextObject.specialkey[i].value = currentObject
}
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
}
if (Next) {
const nextObject = formatData.find((y) => y.id === Next);
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
return result;
};
const response = {
[formatData[0].Key]: processObject(formatData[0]),
};
return response
Is this what you're after?
const input = [
{
"id": "p1", "top": 130, "left" :298, "Key": "test1",
// I've changed this from "special" to "p2"
"Next": "p2"
// rest of input is the same...
},{"id":"p2","Key":"special","specialkey":[{"key":"1","value":"p3"},{"key":"0","value":"p4"},{"key":"2","value":"p5"}],"Next":"","RepeatText": "p8","RepeatTextNew":"p9"},{"id":"p3","user":"aa","Key":"test3","Text":"hi"},{"id":"p4","Key":"special","specialkey":[{"key":"1","value":"p6"},{"key":"0","value":"p7"}]},{"id":"p5","user":"aa","Key":"test5","Text":"hi"},{"id":"p6","user":"aa","Key":"test6","Text":"hi"},{"id":"p7","user":"aa","Key":"test7","Text":"hi"},{"id":"p8","user":"aa","Key":"test8","Text":"hi"},{"id":"p9","user":"aa","Key":"test9","Text": "hi"}];
// Gets an object by its id
const getById = id => input.find(x => x.id === id);
const processObject = ({ Next, specialkey, RepeatText, RepeatTextNew, ...rest }) => {
let processedNext;
if (Next) {
const nextObject = getById(Next);
processedNext = { [nextObject.Key]: processObject(nextObject) };
}
return {
...rest,
// This spread syntax means we don't add the Next or
// specialkey property if it isn't present in the input
// object
...processedNext ? { Next: processedNext } : {},
...RepeatText
? { RepeatText: { [RepeatText]: processObject(getById(RepeatText)) } }
: {},
...RepeatTextNew
? { RepeatTextNew: { [RepeatTextNew]: processObject(getById(RepeatTextNew)) } }
: {},
...specialkey
? {
specialkey: specialkey.map(({ key, value }) => ({
key,
value: processObject(getById(value))
}))
}
: {}
};
}
console.log(processObject(input[0]));
In your code, you seem to be looking up objects by their id, so that's why I changed the first object input's Next from "special" (the Key of the p2 object) to "p2".

Reduce it array to an easier way to map

I'm developing an application and have added new items to my array: type and description.
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
I previously did this to reduce it down to an easier way to map it:
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"]
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
To show the data before I did
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I need to add the description element and type.name to the above. For example for description:
description: e["description"]
To display the elements as in the table:
ITEM
DESCRIPTION
TYPE
202001
202002
I1
item1
type1
100
200
I2
item3
type2
-
300
How do I add and show?
EDIT: console.log(items_dicc[item])
{202001: 100, 202002: 200, description: "item1", type: "type1"}
202001: 100
202002: 200
description: "item1"
type: "type1"
__proto__: Object
{202002: 300, description: "item3", type: "type2"}
202002: 300
description: "item3"
type: "type2"
__proto__: Object
You can add the description and type attribute inside the reduce method like this,
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"],
'description': e['description'],
'type': e.type?.name,
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
console.log(items);
To add the for description and name in the table,
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
<td>{items_dicc[item]?.description}</td>
<td>{items_dicc[item]?.type}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I have been seeing your question regarding these type of tables from yesterday. You have posted several questions with similar things. I suggest you to read some article and understand how JS array methods works instead of asking incremental questions in SO.
Asking in SO might solve your problems for now, but in the long run you will suffer as you don't seem to have a grip on how these things works.
you can simplify your solution like this.
const array = [{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
}
]
const result = array.map(item => {
return Object.keys(item).reduce((a, c) => {
if (c === "date") {
a[item[c].name] = item.price;
} else if (c !== "price" && c !== "id") {
a[c] = (typeof item[c] === "object") ? item[c].name : item[c];
}
return a;
}, {})
});
console.log(result);

Convert object to another object using jQuery

I am getting a result in my JavaScript file which I want to convert into another object.
My original result
[
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
]
Convert this to look like array of objects using jQuery or JavaScript. How can I achieve this?
[
{
"SName": "Set1",
"Id": 3,
"Name": "Name1"
},
{
"SName": "Set1",
"Id": 5,
"Name": "Name2"
},
{
"SName": "Set2",
"Id": 7,
"Name": "Name3"
},
{
"SName": "Set2",
"Id": 8,
"Name": "Name4"
}
]
var data = [
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
];
console.log(data);
var newData = data.reduce(function (newArray, currentSet) {
return newArray.concat(currentSet.Elements.map(function (element) {
return Object.assign( { SName: currentSet.SName }, element);
}));
}, []);
console.log(newData);
The key here is the reduce function. What we are doing is creating a brand new array, by looping through each value of the outer array. We continuously concatenate onto our new array with the values we map from the inner array.
You could iterate the array, the Elements and the properties and build a new object and push it to the result set.
var array = [{ "SName": "Set1", "Elements": [{ "Id": "3", "Name": "Name1" }, { "Id": "5", "Name": "Name2" }] }, { "SName": "Set2", "Elements": [{ "Id": "7", "Name": "Name3" }, { "Id": "8", "Name": "Name4" }] }],
result = [];
array.forEach(function (a) {
a.Elements.forEach(function (b) {
var o = { SName: a.SName };
Object.keys(b).forEach(function (k) {
o[k] = b[k];
});
result.push(o);
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6
var array = [{ "SName": "Set1", "Elements": [{ "Id": "3", "Name": "Name1" }, { "Id": "5", "Name": "Name2" }] }, { "SName": "Set2", "Elements": [{ "Id": "7", "Name": "Name3" }, { "Id": "8", "Name": "Name4" }] }],
result = [];
array.forEach(a => a.Elements.forEach(b => result.push(Object.assign({ SName: a.SName }, b))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this with reduce(), forEach() and Object.assign()
var data = [{
"SName": "Set1",
"Elements": [{
"Id": "3",
"Name": "Name1"
}, {
"Id": "5",
"Name": "Name2"
}]
}, {
"SName": "Set2",
"Elements": [{
"Id": "7",
"Name": "Name3"
}, {
"Id": "8",
"Name": "Name4"
}]
}]
var result = data.reduce(function(r, e) {
e.Elements.forEach(function(o) {
r.push(Object.assign({SName: e.SName}, o))
})
return r;
}, [])
console.log(result)
Here is solution using jQuery, here is jsfiddle:
https://jsfiddle.net/noitse/3uk9qjnf/
I hope you know all key names so it wont be problem to do it fixed.
var json = [
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
]
var newJSON = []
$(json).each(function(index,value){
$(value.Elements).each(function(index1,value1){
newJSON.push({"SName":value.SName,"Id":value1.Id,"Name":value1.Name})
})
})
alert(JSON.stringify(newJSON))
Here is code , what it does it loops through first JSON , then loops through its elements , then it push it to new array
You could use the $.extend method, which lets you create a copy of an object, while merging with another object.
var source = [] // Replace with the initalization of your source array
var destination = [];
for (var i = 0; i < source.length; i++) {
var node = source[i];
for (var j = 0; j < node.Elements.length; j++) {
var subNode = node.Elements[j];
newNode = $.extend(subNode, node);
delete newNode["Elements"];
destination.push(newNode);
}
}
You can run the code in this fiddle.

Why does concurrent flattener returns only 2 inner most children

I can't figure out why this tree 'flattener' is returning only innermost children, the expectation is that it should return flattened tree.
var x = {
"Fields": {
"Id": "1",
"MasterAccountId": "",
"ParentAccountId": "",
"Name": "Name 1"
},
"Children": [{
"Fields": {
"Id": "2",
"MasterAccountId": "1",
"ParentAccountId": "1",
"Name": "Name 2"
},
"Children": [{
"Fields": {
"Id": "5",
"MasterAccountId": "1",
"ParentAccountId": "2",
"Name": "Name 5"
},
"Children": [{
"Fields": {
"Id": "6",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 6"
}
}, {
"Fields": {
"Id": "7",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 7"
}
}]
}]
}]
}
function recurs(n) {
console.log(n.Fields.Name);
return (n.Children != undefined ? $.map(n.Children, recurs) : n);
}
var r = recurs(x);
It returns elements with id 6, 7, while console.logs all 5 of them.
http://plnkr.co/edit/LdHiR86EDBnZFAh6aAlG?p=preview
Your function only returns n if n.Children is undefined. Since you want a flat array with all the objects you have to build one.
function recurs(n) {
var out = [];
out.push(n.Fields);
if (n.Children) {
for (var i=0, c; c = n.Children[i]; i++) {
out.push.apply(out, recurs(c));
}
}
return out;
}

Categories