How to append data in json using map function? - javascript

How can i add additional parameter inside of json using map function
How can I add selected false properties inside of menus array?
Here is the example of Json
const X = [
{
"detail1": "FirstJob",
"menus": [
{
"Order": 1,
"El": " Record Management",
"subSection": [
{
"El": "Check Notification",
"Order": "CheckNotification"
},
{
"El": "Check Record",
"Order": "CheckRecord"
}
]
},
{
"Order": 2,
"El": "Management",
"subSection": [
{
"El": "Notification",
"Order": "Notification"
},
{
"El": "Check",
"Order": "Check"
}
]
},
]
}
]
I tried this but it does add selected inside of the menus array
const filtered = X.map((item) => { return { ...item, selected: false }});
What if i want to add selected properties in subSection array ? how can that be implemnted?

You might need some deeper map
const newX = X.map((el) => ({
...el,
menus: el.menus.map((menuEl) => ({
...menuEl,
selected: false,
})),
}))
const X = [
{
detail1: "FirstJob",
menus: [
{
Order: 1,
El: " Record Management",
subSection: [
{
El: "Check Notification",
Order: "CheckNotification",
},
{
El: "Check Record",
Order: "CheckRecord",
},
],
},
{
Order: 2,
El: "Management",
subSection: [
{
El: "Notification",
Order: "Notification",
},
{
El: "Check",
Order: "Check",
},
],
},
],
},
]
const newX = X.map((el) => ({
...el,
menus: el.menus.map((menuEl) => ({
...menuEl,
selected: false,
})),
}))
console.log(newX)

You just have to extend the map to the subSection array as well.
const X = [{detail1:'FirstJob',menus:[{Order:1,El:' Record Management',subSection:[{El:'Check Notification',Order:'CheckNotification',},{El:'Check Record',Order:'CheckRecord',},],},{Order:2,El:'Management',subSection:[{El:'Notification',Order:'Notification',},{El:'Check',Order:'Check',},],},],},];
const getFormattedData = data => {
return data.map(d => {
return {
...d,
menus: d.menus.map(m => {
return {
...m,
subSection: m.subSection.map(s => {
return {
...s,
selected: false
}
})
}
})
}
})
}
console.log(getFormattedData(X));
.as-console-wrapper {
max-height: 100% !important;
}

Try this for adding selected at the top level
X.map(
item => {
item["selected"]=false;
return item;
}
);
and this for adding the selected field in the subSection
X.map(
item => {
item["menus"].map(
menuItem => {
menuItem["selected"] = true;
}
);
return item;
}
);

Related

json filter nested array with javascript

I want to pull with javascript: {"subNav0", "subNav1", "subNav2", "subNav3", "subNav4", "subNav5"}.
my json:
var data = {
"menus":{
"GrandparentNav0":{
"name":"TopNav",
"items":[
{
"name":"ParentNav0",
"iconClass":"",
"items":[
{
"name":"ParentNav1",
"iconClass":"",
"items":[
{
"name":"subNav0",
"iconClass":""
},
{
"name":"subNav1",
"iconClass":""
},
{
"name":"subNav2",
"iconClass":""
},
{
"name":"subNav3",
"iconClass":""
},
{
"name":"subNav4",
"iconClass":""
},
{
"name":"subNav5",
"iconClass":""
}
]
},
]
}
]
}
},
};
i know basic filter of an array:
data .forEach(function(o) {
o.variable = o.variable.filter(s => s.value == value);
});
I dont know how to get through menus, GrandparentNav0 to pull the subNav(s)
By "pull the subNav(s)" do you mean like accessing it through something like bracket notation?
let subNavs = data['menus']['GrandparentNav0']['items'][0]['items']
console.log(subNavs)
/* would return
[
{
"name": "subNav0",
"iconClass": ""
},
{
"name": "subNav1",
"iconClass": ""
},
{
"name": "subNav2",
"iconClass": ""
},
{
"name": "subNav3",
"iconClass": ""
},
{
"name": "subNav4",
"iconClass": ""
},
{
"name": "subNav5",
"iconClass": ""
}
]
*/
Here is a solution using object-scan. This might be overkill for your requirements, however as you run into other use cases it's a Swiss army knife that makes these types of data interactions very clean
// const objectScan = require('object-scan');
const data = { menus: { GrandparentNav0: { name: 'TopNav', items: [ { name: 'ParentNav0', iconClass: '', items: [ { name: 'ParentNav1', iconClass: '', items: [ { name: 'subNav0', iconClass: '' }, { name: 'subNav1', iconClass: '' }, { name: 'subNav2', iconClass: '' }, { name: 'subNav3', iconClass: '' }, { name: 'subNav4', iconClass: '' }, { name: 'subNav5', iconClass: '' } ] } ] } ] } } };
const result = objectScan(['menus.GrandparentNav0.items[0].items[0].items[*].name'], { reverse: false, rtn: 'value' })(data);
console.log(result);
// => [ 'subNav0', 'subNav1', 'subNav2', 'subNav3', 'subNav4', 'subNav5' ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#14.0.0"></script>
Disclaimer: I'm the author of object-scan

Filter an array of objects using multiple values from the object

So I have an array of objects that looks like this :
let medicines = [
{
id:3340,
name:nutraplus,
description:"some medicine",
ingredients: [{
ingredient:"glycerol"
},
{
ingredient:"Morphine"
}
]
},
{
id:3320,
name:Panadol,
description:"tablet",
ingredients: [{
ingredient:"Paracetamol"
},
{
ingredient:"Some stuff"
}
]
}
]
I want to to be able to filter by name and by ingredient name I have acheived the former by doing this :
computed: {
medicines() {
return this.$store.state.medicines.filter(med => {
//this.search is the what comes after typing in search bar
return med.name.toLowerCase().includes(this.search.toLowerCase())
})
},
}
Its vue.js so the computed() stuff anyways this works perfectly when searching by name however i also want to be able to search by ingredients from the same search bar. I tried something like this :
edicines() {
return this.$store.state.medicines.filter(med => {
return med.name.toLowerCase().includes(this.search.toLowerCase()) || med.ingredients.map(ing=>{
ing.ingredient.name.toLowerCase().includes(this.search.toLower)
})
})
}
But it didn't work. Any ideas on how to get this working? Thank you for your time.
Haven't used vue in the example, you just need to extract the logic behind the filtering that I have done (Simple JS filtering)
As example -
Try searching for 'Para' - It must return the entries with name/ingredient containing Para
Try searching for 'stuff' - It should return two entries (since both medicine in that array consist of 'some stuff' as ingredient)
let medicines = [{
id: 3340,
name: 'nutraplus',
description: "some medicine",
ingredients: [{
ingredient: "glycerol"
},
{
ingredient: "Morphine"
},
{
ingredient: "Some stuff"
}
]
},
{
id: 3320,
name: 'Panadol',
description: "tablet",
ingredients: [{
ingredient: "Paracetamol"
},
{
ingredient: "Some stuff"
}
]
},
{
id: 3311,
name: 'Amazin',
description: "tablet"
}
];
const form = document.querySelector('form')
form.addEventListener('submit', (e) => {
e.preventDefault();
const searchValue = form.searchText.value.toLowerCase();
const matchValue = medicines.filter(medicine => {
return medicine.name.toLowerCase().includes(searchValue) || (medicine.ingredients ? medicine.ingredients.filter(ingredientObj => {
return ingredientObj.ingredient.toLowerCase().includes(searchValue);
}).length > 0 : false);
});
document.querySelector('.result').textContent = JSON.stringify(matchValue, null, 4);
});
pre {
background: #c5c5c5;
}
<form>
<label for="searchText"></label>
<input type="text" id="searchText" name="searchText">
<button>Search</button>
</form>
<pre class='result'></pre>
This should work.
let medicines = [
{
id:3340,
name:"nutraplus",
description:"some medicine",
ingredients: [{
ingredient:"glycerol"
},
{
ingredient:"Morphine"
}
]
},
{
id:3320,
name:"Panadol",
description:"tablet",
ingredients: [{
ingredient:"Paracetamol"
},
{
ingredient:"Some stuff"
}
]
}
];
const searchPhrase = "Paracetamol";
const filteredByName = medicines.filter((medicine) => {
return medicine.name.toLowerCase() === searchPhrase.toLowerCase();
});
const filteredByIngredient = medicines.filter((medicine) => {
return medicine.ingredients.some((item) => item.ingredient.toLowerCase() === searchPhrase.toLowerCase());
})
const result = [...filteredByName, ...filteredByIngredient];
console.log(result)

Push an Object Into a complicated arra

I'm trying to push an Object into a complicated array I'm thinking about something like that"DUMMY_PLACES[0].todos.byIds.push" but I don't succeed to do it. I have an(id, content), and the completed need to be by default false. hope for help I believe that's not too complicated but I can't figure it out. ps: if someone can also help with the delete option I would be happy.
for example, I get (5,test5). I want.
const DUMMY_PLACES = [
{
todos: {
allIds: [1, 2, 3, 4,],
byIds: {
"1": {
content: "test1",
completed: false,
},
"2": {
content: "test2",
completed: false,
},
"3": {
content: "test3\\",
completed: false,
},
"4": {
content: "test4",
completed: false,
},
},
},
visibilityFilter: "all",
},
];
const DUMMY_PLACES = [
{
todos: {
allIds: [1, 2, 3, 4,5],
byIds: {
"1": {
content: "test1",
completed: false,
},
"2": {
content: "test2",
completed: false,
},
"3": {
content: "test3\\",
completed: false,
},
"4": {
content: "test4",
completed: false,
},
"5": {
content: "test5",
completed: false,
},
},
},
visibilityFilter: "all",
},
];
Here take a look at the addTodo function which creates a new instance of the todoList with a new element added to the end of it. And it also modifies the list of Ids. I've commented almost every line, so it should be pretty straightforward.
let todoList = [
{
todos: {
allIds: [1, 2, 3, 4],
byIds: {
"1": {
content: "test1",
completed: false,
},
"2": {
content: "test2",
completed: false,
},
"3": {
content: "test3",
completed: false,
},
"4": {
content: "test4",
completed: false,
},
},
},
visibilityFilter: "all",
},
];
let addTodo = (sourceArray, el) => {
// Create a copy of an original array
let targetArray = [];
Object.assign(targetArray, sourceArray);
let todos = targetArray[0].todos;
// Calculate the Id for a new element
let newId = Object.keys(todos.byIds).length + 1;
// Add new Id to the `allIds` list
todos.allIds.push(newId);
// Create a new element
todos.byIds[newId] = {
content: el,
completed: false
}
return targetArray;
}
todoList = addTodo(todoList, 'test5');
todoList = addTodo(todoList, 'test6');
todoList = addTodo(todoList, 'test7');
console.log(JSON.stringify(todoList));
And the output should be:
[
{
"todos":{
"allIds":[
1,
2,
3,
4,
5,
6,
7
],
"byIds":{
"1":{
"content":"test1",
"completed":false
},
"2":{
"content":"test2",
"completed":false
},
"3":{
"content":"test3",
"completed":false
},
"4":{
"content":"test4",
"completed":false
},
"5":{
"content":"test5",
"completed":false
},
"6":{
"content":"test6",
"completed":false
},
"7":{
"content":"test7",
"completed":false
}
}
},
"visibilityFilter":"all"
}
]
Maybe you need something like this
const DUMMY_PLACES = [ { todos: { allIds: [1, 2, 3, 4], byIds: { "1": { content: "test1", completed: false, }, "2": { content: "test2", completed: false, }, "3": { content: "test3\\", completed: false, }, "4": { content: "test4", completed: false, }, }, }, visibilityFilter: "all", }, ];
function pushObject(id, content) {
DUMMY_PLACES[0].todos.allIds.push(id);
DUMMY_PLACES[0].todos.byIds[id] = { ...content, completed: false };
}
pushObject(5, { content: "test5" });
console.dir(DUMMY_PLACES);
Your code lacks encapsulation. Best approach here would be to create a new class and create a setter for this.
EDIT with example:
class UserTodo
{
constructor( visibilityFilter = 'all' )
{
this._visibilityFilter = visibilityFilter;
this._byIds = new Map();
}
/**
* #details Add a todo with the content text
*/
addTodo( title, content )
{
const value = {
content,
completed: false
}
this._byIds.set( title, value );
}
/**
* #Details Decide if you want to get the entire object or just the content here
*/
getTodo( title )
{
return this._byIds.get( title );
}
completeTodo( title )
{
this._byIds.get( title ).completed = true;
}
/**
* #details As a bonus on how to delete a specific todo
*/
deleteTodo( title )
{
this._byIds.delete( title );
}
/**
* #details this will return allIds from the example
*/
getAllIds()
{
return Array.from( this._byIds.keys() );
}
/**
* #details this will return visibilityFilter from the example
*/
getVisibility()
{
return this._visibilityFilter;
}
// Implement other getters
}
// Why is this an array even?
const DUMMY_PLACES = [];
DUMMY_PLACES.push( new UserTodo( 'all' ) );
const toDoTitle = 'Some Title';
// Add a new todo
DUMMY_PLACES[0].addTodo( toDoTitle, 'Do Something' );
// Check that the todo is added
console.log( DUMMY_PLACES[0].getTodo( toDoTitle ) );
// Complete it
DUMMY_PLACES[0].completeTodo( toDoTitle );
// Check that it is completed
console.log( DUMMY_PLACES[0].getTodo( toDoTitle ) );

Convert multiple json object into array of object

My data is currently stored in this format:
{
"Site1":{
"week":[
{
"access":1
},
{
"access":8
}
]
},
"Site2":{
"week":[
{
"access":16
}
]
},
"Site3":{
"week":[
{
"access":2
},
{
"access":6
},
{
"access":2
}
]
}
}
And I need to convert it into this format:
[
{
"id":"Site1",
"access":[1,8]
},
{
"id":"Site2",
"access":[16]
},
{
"id":"Site3",
"access":[2,6,2]
}
]
As you can see, I also need to take the keys (site name) and make them the "id" values.
Any ideas on how I can do this in JavaScript (I'm using angular v9)? I'm not very good at restructuring that type of data.
You can first take entries and then map it:
var data={ "Site1":{ "week":[ { "access":1 }, { "access":8 } ] }, "Site2":{ "week":[ { "access":16 } ] }, "Site3":{ "week":[ { "access":2 }, { "access":6 }, { "access":2 } ] }};
var result = Object.entries(data).map(([k,v])=>({id:k, access: v.week.map(p=>p.access)}));
console.log(result);
Object.keys()
map()
const data = {
Site1: {
week: [
{
access: 1,
},
{
access: 8,
},
],
},
Site2: {
week: [
{
access: 16,
},
],
},
Site3: {
week: [
{
access: 2,
},
{
access: 6,
},
{
access: 2,
},
],
},
};
const result = Object.keys(data).map(key => ({
id: key,
access: data[key].week.map(w => w.access),
}));
console.log(result);
you can simply use this code for your desired result.
Object.keys(data).map(key => (
{
id: key,
access: data[key].week.map(obj => obj.access),
}
))
Let me know if you face any issue.

Find the value and delete the whole object associated with that array from a deeply nested array of object

I browsed So many questions to find out logics for finding Index in a deeply nested array of object, I didn't find it useful for my requirement though.
in search of Solution in Javascript, Lodash/Underscore would be Fine too.
Let me just phrase out the Whole requirement, Hoping I get a path to find the solution for this issue.
Requirement:
I have an array of objects
arrObj =[
{
"id":3208,
"name":"List",
"issueResponses":[
],
"isActive":false
},
{
"id":3209,
"name":"Me",
"issueResponses":[
],
"isActive":false
},
{
"id":3314,
"name":"SNew",
"issueResponses":[
],
"isActive":false
},
{
"id":3315,
"name":"Olive",
"issueResponses":[
{
"id":3282,
"name":"related to Olive",
"issueResponses":[
],
"isActive":false
},
{
"id":3316,
"name":"My olives are not yet picked",
"issueResponses":[
{
"id":3317,
"name":"Pickup Not Done",
"issueResponses":[
],
"isActive":false
}
]
}
]
}
]
As we can see its deeply nested, I have another array
delValue = [3317,3282], And tomorrow it might be anything in these Deep Nesting.
I have to find these delValue arrays in arrObj and delete all those Objects which has "id" as these Values.
I am trying to solve this in a generic way which can support any number deep search Level and Deletion of the Object from that.
Please help me out in this, if More Information needed will be happy to provide.
You can use filter to achieve this:
function removeDeletions(array, deletion) {
return array.filter(el => {
if (Array.isArray(el.issueResponses)) el.issueResponses = removeDeletions(el.issueResponses, deletion);
return ! deletion.includes(el.id);
})
}
DEMO:
let arrObj = [{
"id": 3208,
"name": "List",
"issueResponses": [
],
"isActive": false
},
{
"id": 3209,
"name": "Me",
"issueResponses": [],
"isActive": false
},
{
"id": 3314,
"name": "SNew",
"issueResponses": [
],
"isActive": false
},
{
"id": 3315,
"name": "Olive",
"issueResponses": [{
"id": 3282,
"name": "related to Olive",
"issueResponses": [
],
"isActive": false
},
{
"id": 3316,
"name": "My olives are not yet picked",
"issueResponses": [{
"id": 3317,
"name": "Pickup Not Done",
"issueResponses": [
],
"isActive": false
}]
}
]
}
]
let delValue = [3317, 3282];
function removeDeletions(array, deletion) {
return array.filter(el => {
if (Array.isArray(el.issueResponses)) el.issueResponses = removeDeletions(el.issueResponses, deletion);
return !deletion.includes(el.id);
})
}
console.log(removeDeletions(arrObj, delValue));
Just keep checking issueResponses - like so:
function deleteIssueResponses(issues, ids) {
for (let i = issues.length; i >= 0; i--) {
if (issues[i].issueResponses.length) {
deleteIssueResponses(issues[i].issueResponses, ids);
}
if (ids.contains(issues[i].id)) {
issues.splice(i, 1);
}
}
}
And call it:
deleteIssueResponses(arrObj, [3317,3282]);
This should be quite simple to solve with some recursion. This function will delete the given ids in the array passed to it, or else call itself to do the same for the nested arrays.
function deleteIds(arr, ids) {
for (let i = 0; i < arr.length; i++) {
if (ids.indexOf(arr[i].id) !== -1) {
arr.splice(i, 1);
i--;
} else {
deleteIds(arr[i].issueResponses, ids);
}
}
}
Call with deleteIds(arrObj, delValue) as in your question.
We use object-scan for basic data processing tasks like this. Once you wrap your head around how to use it, it's pretty good and powerful. Here is how you could answer your questions:
// const objectScan = require('object-scan');
const prune = (values, data) => objectScan(['**[*].id'], {
rtn: 'count',
filterFn: ({ gparent, gproperty, value }) => {
if (values.includes(value)) {
gparent.splice(gproperty, 1);
return true;
}
return false;
}
})(data);
const arrObj = [{ id: 3208, name: 'List', issueResponses: [], isActive: false }, { id: 3209, name: 'Me', issueResponses: [], isActive: false }, { id: 3314, name: 'SNew', issueResponses: [], isActive: false }, { id: 3315, name: 'Olive', issueResponses: [{ id: 3282, name: 'related to Olive', issueResponses: [], isActive: false }, { id: 3316, name: 'My olives are not yet picked', issueResponses: [{ id: 3317, name: 'Pickup Not Done', issueResponses: [], isActive: false }] }] }];
console.log(prune([3317, 3282], arrObj)); // return number of deletes
// => 2
console.log(arrObj);
// => [ { id: 3208, name: 'List', issueResponses: [], isActive: false }, { id: 3209, name: 'Me', issueResponses: [], isActive: false }, { id: 3314, name: 'SNew', issueResponses: [], isActive: false }, { id: 3315, name: 'Olive', issueResponses: [ { id: 3316, name: 'My olives are not yet picked', issueResponses: [] } ] } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#15.0.0"></script>
Disclaimer: I'm the author of object-scan

Categories