I have an array of objects like this
[ { '0': { notify_item: '1' } },
{ '1': { notify_item: '2' } },
{ '2': { notify_item: '3' } } ]
Now I want to replace '0' with some Text like 'Invoice' and the value of that '0' key with value like this { 'sms': true,email:'false' }.
And I want to replace every key with some text and their value with something like this { 'sms': true,email:'false' }
so after replacing I want something like this
[ { 'Invoice': { 'sms': true,email:'false' } },
{ 'ManualReminder': { 'sms': true,email:'false' },
{ 'AutomaticReminder': { 'sms': true,email:'false' } ]
I am not able to understand I have tried the splice method but it is not working. Please give some hint
Iterate through the array using Array.map function. In map function you can use switch statements to match the appropriate values and return the desired output.
var arr = [{
'0': { notify_item: '1' }
},
{
'1': { notify_item: '2' }
},
{
'2': { notify_item: '3' }
}];
var modifiedArr = arr.map(function(item) {
var newItem = {};
for ( var key in item) {
var newItemKey = getKey(key);
var newItemValue = getValue(item[key]);
}
newItem[newItemKey] = newItemValue;
return newItem;
});
console.log(modifiedArr);
function getKey (key) {
switch(key) {
case '0':
return 'Invoice';
case '1':
return 'ManualReminder';
case '2':
return 'AutomaticReminder';
default:
return 'default';
}
}
function getValue (value) {
switch(value.notify_item) {
case '1':
return { 'sms': true,email:'false' };
case '2':
return { 'sms': true,email:'false' };
case '3':
return { 'sms': true,email:'false' };
default:
return 'default';
}
}
[ { 'Invoice': { 'sms': true,email:'false' } },
{ 'ManualReminder': { 'sms': true,email:'false' },
{ 'AutomaticReminder': { 'sms': true,email:'false' } ]
This is a job for map.
It's also harder than it should be because the structure of your data is quite weird. Wouldn't something like { notification_type: 0, notify_item: 1 } be easier to work with?
It may not be needed to convert data, you may just get new result.
Maybe something like this will help you.
var input = [ { '0': { notify_item: '1' } },
{ '1': { notify_item: '2' } },
{ '2': { notify_item: '3' } } ];
var keyMap = {'0': 'Invoice', '1': 'ManualReminder', '2': 'AutomaticReminder'};
var result = Object.keys(input).map(function (key) {
var item = {},
value = input[key]; //{notify_item:'1'} for first iteration
//do your logic to convert {notify_item: '1' | '2' | '3'}
item[keyMap[key]] = ''; //to whatever you need
return item;
});
console.log(result);
Related
Following Unexpected outcome when modifying an object in a function
I learned that i have to clone the item passed to the function before changing it and returning it, and it worked for the said example, but when i tried it in my code which was a recursive code, it didn't work, here is an example showing this:
As you can see i intend to update the property B if it exists and if it doesn't i want to create a property B and then give it last value, but for some reason this fails !, of course if i create the property B before hand (before calling it recursively), i can give the value to it, but i don't know why this is needed or why my current code doesn't work!
function addB(item) {
let newItem = { ...item };
if (newItem.B) {
newItem.B.value = "I am B";
} else {
newItem.B = {
value: "I am B"
};
}
if (newItem.children) {
newItem.children.forEach(child => {
//if you uncomment the code below, the code works!
//child.B = {};
child = addB(child);
});
}
return newItem;
}
function App() {
let parent = {
id: 0,
children: [
{
id: 1,
children: [
{
id: 3
},
{
id: 4
}
]
},
{
id: 2
}
]
};
parent = addB(parent);
console.log(parent);
}
Current output:
Expected output:
You can see this example and its result in this CodeSandBox
I think you can do the following:
function addB(item) {
const newItem = { ...item, B: { value: 'I am B' } };
if (newItem.children) {
newItem.children = newItem.children.map(addB);
}
return newItem;
}
If you want to copy the B property if it exist and only set B.value then you can do:
const newItem = { ...item, B: { ...item.B, value: 'I am B' } };
function addB(item) {
const newItem = { ...item, B: { ...item.B,value: 'I am B' } };
if (newItem.children) {
newItem.children = newItem.children.map(addB);
}
return newItem;
}
console.log(
addB({
children: [
{},
{ children: [{}, { B: { other: 2 } }] },
{ B: { something: 1 } },
],
})
);
Another way to write this is:
var addB = item => ({
...item,
B: { ...item.B, value: 'I am B' },
...(item.children
? { children: item.children.map(addB) }
: undefined),
});
Following is my code to get the languages with Language id and language text
for (var p in $scope.bulk.Langugaes) {
$scope.lsLanguagewithTextndValue.push($scope.bulk.Langugaes[p].Value, $scope.bulk.Langugaes[p].Text);
}
but for above code the value in lsLanguagewithTextndValue
0:"1"
1:"Marathi"
2:"2"
3:"English"
4:"4"
5:"Hindi"
6:"3"
7:"French"
But I want output like this
1:Marathi
2:English
3.Hindi
4.French
$scope.lsLanguagewithTextndValue.push({ $scope.bulk.Langugaes[p].Value: $scope.bulk.Langugaes[p].Text });
Multiple arguments in .push just pushes each argument in to the array.
If you want to add a pair key - value do it like this:
obj[key] = value;
In your case it should be something like this:
for (var p in $scope.bulk.Langugaes) {
$scope.lsLanguagewithTextndValue[$scope.bulk.Langugaes[p].Value] = $scope.bulk.Langugaes[p].Text;
}
Try this.
const $scope = {
bulk: {
Languages: {
ln1: { value: 1, text: 'Marathi' },
ln2: { value: 2, text: 'English' },
ln3: { value: 3, text: 'Hindi' },
ln4: { value: 4, text: 'French' }
}
},
lsLanguagewithTextndValue: []
}
// just to make it more readable
const langs = $scope.bulk.Languages;
for (let p in langs) {
$scope.lsLanguagewithTextndValue.push({[langs[p].value]: langs[p].text})
}
console.log($scope.lsLanguagewithTextndValue);
In this case use map Array map. This function make a new array with elements of another.
$scope.lsLanguagewithTextndValue =
$scope.bulk.Langugaes.map((langugaes) => {
// langugaes its a element of $scope.bulk.Langugaes for example
// $scope.bulk.Langugaes[p]
return {langugaes.Value: langugaes.Text}
})
Result:
{
"1": "Marathi"
},
{
"2": "English"
},
{
"3": "Hindi"
},
{
"4": "French"
}
i have this json array.
[ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ]
and here I'm trying to console log the value of every msg by doing this.
jsonArray.forEach(function(element) {
console.log(element);
console.log(element['0']);
});
output
{ '0': { msg: 'helloworld1' } }
{ '0': { msg: 'helloworld2' } }
undefined
undefined
the question is, how do i print out the values of msg keys and why is it returning undefined?
Try to parse the data again as following:
var jsonArray = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ]
jsonArray = JSON.parse(JSON.stringify(jsonArray));
jsonArray.forEach(function(element) {
console.log(element['0'].msg);
});
This JSON.stringify should convert the data to string then JSON.parse will convert it to JS Object.
You can use lodash for this.
var array = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ];
_.mapValues(array, function(array2) {
_.mapValues(array2, function(array3){
console.log(array3.msg)})
})
This will return the value in 'msg' keys. Here is the lodash documentation. loadh-map
You have no problem at all, apparently.
Check out: https://repl.it/Gh3i/0
If you click 'run' you get
helloworld1
helloworld2
The same applies if you use integers:
var jsonArray = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ];
jsonArray.forEach(function(element) {
console.log(element[0].msg);
});
Please find the updated code attached below
var jsonArray=[{"0":{"msg":"helloworld1"}},{"0":{"msg":"helloworld2"}}];
jsonArray.forEach(function(element) {
console.log(element[0].msg);
});
I have array of objects like this. And they have duplicated property 'contactName' values
[
{
categoryId:1
categoryName:"Default"
contactId:141
contactName:"Anonymous"
name:"Mobile"
value:"+4417087654"
},
{
categoryId:1
categoryName:"Default"
contactId:325
contactName:"Anonymous"
name:"Email"
value:"test2#gmail.com"
},
{
categoryId:1
categoryName:"Default"
contactId:333
contactName:"Anonymous"
name:"Email"
value:"ivdtest#test.com"
}
]
I want to merge them in one object by the name of property 'contactName'
To something like this
[
{
categoryId: 1,
categoryName: "Default",
contactId: 141,
contactName: "Anonymous",
names: {
1: "Mobile",
2: "Email",
3: "Email"
},
values: {
1: '+2234324',
2: "ivdtest#test.com",
3: "test2#gmail.com"
}
}
];
Edit: How can I group objects also by categoryName ?
var grouped = _.groupBy(input, 'contactName');
var output = _.map(grouped, function(entries) {
return _.extend(
_.pick(entries[0], 'categoryId', 'categoryName', 'contactId', 'contactName'),
{
names: _.indexBy(_.pluck(entries, 'name'), function(val, index) { return index +1; }),
values: _.indexBy(_.pluck(entries, 'value'), function(val, index) { return index +1; })
}
);
});
https://jsfiddle.net/f1x4tscu/3/
Another variant with array inside the object
var grouped = _.groupBy(this.contacts, 'contactName');
var output = _.map(grouped, function (entries) {
return _.extend(
_.pick(entries[0], 'categoryId', 'categoryName', 'contactId', 'contactName'),
{
addresses: _.map(entries, function (m) {
return {
name: m.name,
value: m.value
}
}),
}
);
});
I have an array of objects similar to the following block of code:
var arr = [
{
text: 'one',
children: [
{
text: 'a',
children: [
{
text: 'something'
}
]
},
{
text: 'b'
},
{
text: 'c'
}
]
},
{
text: 'two'
},
{
text: 'three'
},
{
text: 'four'
}
];
In the above structure, I want to search a string in text property and I need to perform this search over all the children.
For example, if I search for something, the result should be an array of object in the following form:
[
{
children: [
{
children: [
{
text: 'something'
}
]
}
]
}
];
Notice all the text properties that do not match the input string something have been deleted.
I have come up with the following block of code using Array.prototype.filter. However, I can still see extra properties in the result:
function search(arr, str) {
return arr.filter(function(obj) {
if(obj.children && obj.children.length > 0) {
return search(obj.children, str);
}
if(obj.text === str) {
return true;
}
else {
delete text;
return false;
}
});
}
Here is the fiddle link: https://jsfiddle.net/Lbx2dafg/
What am I doing wrong?
I suggest to use Array#forEach, because filter returns an array, which is needed, but not practical for this purpose, because it returns all children with it.
This proposal generates a new array out of the found items, with the wantes item text and children.
The solution works iterative and recursive. It finds all occurences of the search string.
function filter(array, search) {
var result = [];
array.forEach(function (a) {
var temp = [],
o = {},
found = false;
if (a.text === search) {
o.text = a.text;
found = true;
}
if (Array.isArray(a.children)) {
temp = filter(a.children, search);
if (temp.length) {
o.children = temp;
found = true;
}
}
if (found) {
result.push(o);
}
});
return result;
}
var array = [{ text: 'one', children: [{ text: 'a', children: [{ text: 'something' }] }, { text: 'b' }, { text: 'c' }] }, { text: 'two' }, { text: 'three' }, { text: 'four' }];
console.log(filter(array, 'something'));
Your function search returns an array with object from "parent" level, that's why you "still see extra properties in the result".Secondly, this line delete text; doesn't delete an object or object property - it should be delete obj.text;. Here is solution using additional Array.map fuinction:
function search(arr, str) {
return arr.filter(function(obj) {
if (obj.text !== str) {
delete obj.text;
}
if (obj.children && obj.children.length > 0) {
return search(obj.children, str);
}
if (obj.text === str) {
return true;
} else {
delete obj.text;
return false;
}
});
}
var result = search(arr, 'something').map(function(v) { // filtering empty objects
v['children'] = v['children'].filter((obj) => Object.keys(obj).length);
return {'children':v['children'] };
});
console.log(JSON.stringify(result,0,4));
The output:
[
{
"children": [
{
"children": [
{
"text": "something"
}
]
}
]
}
]
https://jsfiddle.net/75nrmL1o/