Here is a JSON array below.
let data = {
"list": [
{ "name": "my Name", "id": 12, "type": "car owner" },
{ "name": "my Name2", "id": 13, "type": "car owner2" },
{ "name": "my Name4", "id": 14, "type": "car owner3" },
{ "name": "my Name4", "id": 15, "type": "car owner5" }
]
}
Now as i want to access the "name" in the above JSON list here is my approach so far below.
console.log(data.list.filter(record => record.name.match(/my Name2.*/)));
Now i want to pass a dynamic variable in between the /my Name2.*/ how can i do that.
Suppose i want to pass let str = 'my Name' like this way /str.*/ how is it possible and i want to only get the list array of "name" only rather than whole bunch of existing properties like id and type.
To use a variable inside of a regular expression, use the RegExp constructor. Then you can use map to keep only the names:
/* Same data as yours */ const data = {list:[{name:"my Name",id:12,type:"car owner"},{name:"my Name2",id:13,type:"car owner2"},{name:"my Name4",id:14,type:"car owner3"},{name:"my Name4",id:15,type:"car owner5"}]};
const str = "my Name2";
const regex = new RegExp(str + ".*");
const res = data.list
.filter(record => record.name.match(regex))
.map(record => record.name);
console.log(res);
let data = {
"list": [
{ "name": "my Name", "id": 12, "type": "car owner" },
{ "name": "my Name2", "id": 13, "type": "car owner2" },
{ "name": "my Name4", "id": 14, "type": "car owner3" },
{ "name": "my Name4", "id": 15, "type": "car owner5" }
]
}
let input='my Name'
console.log(data.list.filter(record => record.name===input).map(record=>record.name));
Related
I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:
[
{
"id": 1,
"name": "test",
"category": {
"id": 1,
"name": "Cookies",
},
},
{
"id": 2,
"name": "test2",
"category": {
"id": 2,
"name": "Candy",
},
}
]
Then I'm trying to filter the objects on the category name based on another array of categories.
I've created a function for this:
function onSelectCategory(category) {
let receiptsList = receipts.filter((a) =>
a.category.includes(category.name)
);
setReceiptsView(receiptsList);
setSelectedCategory(category);
}
const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);
When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.
Since the param seems to be an array of objects, you need to use Array#some for comparison instead:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const receiptsList = receipts.filter(({ category }) =>
categories.some(({ name }) => name === category.name)
);
console.log(receiptsList);
Another solution using Set:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const categorySet = new Set(categories.map(({ name }) => name));
const receiptsList = receipts.filter(({ category }) =>
categorySet.has(category.name)
);
console.log(receiptsList);
Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.
Try this:
a.category.name == category;
instead of
a.category.includes(category.name)
I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.
I have object like this:
{
"id": 1,
"name": "first",
"sections": [
{
"id": 1,
"title": "First section",
"contents": [
{
"id": "123",
"title": "Sample title 1",
"description": "<html>code</html>",
},
{
"id": "124",
"title": "Sample title 2",
"description": "<html>code</html>"
},
{
"id": "125",
"title": "Some other sample",
"description": "<html>code</html>"
}
]
},
{
"id": 2,
"title": "Second section",
"contents": [
{
"id": "126",
"title": "Sample title 126",
"description": "<html>code</html>"
},
{
"id": "127",
"title": "Sample title 127",
"description": "<html>code</html>"
}
]
}
]
}
I want to remove specific object from contents array by its id (all those ids are unique).
I can easily find element I want to remove, but I'm unable to find in which section this element is to splice it later.
obj.sections.forEach(function(section) {
section.contents.forEach((content) => {
if (content.id == 125) {
console.log(content)
console.log(section)
}
})
})
In above code console.log(sections) returns undefined. How can I get position in sections array which contains contents array that has specific id. For example, id: 125 would return sections position 0, so I can use splice to remove that element.
If my approach is completely wrong please point me in right direction, thanks :)
You could use .filter() instead of .splice(). .filter() will keep all items which you return true for and discard of those which you return false for. So, if the current section's content's object has an id equal to the one you want to remove you can return false to remove it, otherwise return true to keep that item. You can use this with .map() to map each section object to a new one with an updated contents array:
const obj = { "id": 1, "name": "first", "sections": [ { "id": 1, "title": "First section", "contents": [ { "id": "123", "title": "Sample title 1", "description": "<html>code</html>", }, { "id": "124", "title": "Sample title 2", "description": "<html>code</html>" }, { "id": "125", "title": "Some other sample", "description": "<html>code</html>" } ] }, { "id": 2, "title": "Second section", "contents": [ { "id": "126", "title": "Sample title 126", "description": "<html>code</html>" }, { "id": "127", "title": "Sample title 127", "description": "<html>code</html>" } ] } ] };
const idToRemove = 125;
obj.sections = obj.sections.map(
sec => ({...sec, contents: sec.contents.filter(({id}) => id != idToRemove)})
);
console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore */
Why not use a simple filter for accomplishing the task. Also, it will be much cleaner and immutable way of doing it.
let newArrWithoutContentWithGivenId = obj.sections.map(section =>
({...section, contents: section.contents.filter(content =>
content.id != 125)}));
Here, we are mapping each section whose content does not contain the ID 125. In short, section > content.id != 125 will be removed from the new array.
Hope it helps :)
Note: Code is not tested, it is just to help you find a way to do it cleanly.
You only need to use the second argument of forEach :)
obj.sections.forEach(function(section, sectionIndex) {
section.contents.forEach((content, contentIndex) => {
if (content.id == 125) {
// use the sectionIndex and contentIndex to remove
}
})
})
I am looking for a way to replace a bunch of data in a JSON file without replacing another part of it:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
],
"compteur": [
{
"id": 8
}
]
}
I manage to get everything that is in between the brackets of "task" in a variable.
My current issue is that I need to replace only what's inside the bracket and not affect the other parts of the file.
This is my code for retrieving the data of "tasks":
function RemoveNode(idToDelete) {
return jsonData.task.filter(function(emp) {
if (emp.id == idToDelete) {
return false;
}
return true;
});
}
var newData = RemoveNode(idToDelete);
arr1 = JSON.stringify(newData, null, 4);
console.log("arr1", arr1);
The console.log gives me:
arr1 [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
]
I actually need to replace this in the original JSON File but I have absolutely no idea how to achieve this.
You can use the spread operator, this will override the task data with your new filtered data
const removeNode = (idToDelete) =>
jsonData.task.filter((emp) => emp.id != idToDelete);
const newData = RemoveNode(idToDelete);
const updatedJSONData = {...jsonData, task: newData};
If your JSON file is not too large, you could consider changing the task array in your JS object (once you've read or imported it into your program) and then re-writing the json file.
JSON file before the program runs:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 6,
"title": "fddsfsd",
"description": "fsdfsd"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}
],
"compteur": [
{
"id": 8
}
]
}
Let's say we want to remove task objects with id=6. The code:
const myFileContents = require('./myFile.json');
const fs = require('fs');
const removeIdFromTasks = (taskList,idToRemove) => {
return taskList.filter(task => task.id!=idToRemove);
}
const writeJsonFile = (fileName,content) => {
fs.writeFile(fileName,content,(err) => {
if(err){
console.error(`Error in writing json file: ${e.message}`);
} else {
console.log(`File written`);
}
})
}
myFileContents.task = removeIdFromTasks(myFileContents.task,6);
writeJsonFile(`myFile.json`,JSON.stringify(myFileContents));
The same file after execution:
{
"task": [
{
"id": 5,
"title": "dave",
"description": "test"
},
{
"id": 7,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
},
{
"id": 8,
"title": "fddsfssdfsdfd",
"description": "fsdfsd"
}],
"compteur": [
{
"id": 8
}]
}
I am trying to grab a value of a key inside of an object in an array which itself is an object in an array.
Here is what it looks like:
var books = [
{
"title": "title1",
"author": "author1",
"users": [
{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
},
What I am trying to do, 2 things:
First:
when I click on a user name in the HTML, I want to match the name clicked with the same user name in all the objects it is present in.
Second:
display the title of the books this user name is present in.
For example: when I click on Jose Miguel I want to see the 2 books he has read.
At the moment I have this:
var btnUser = document.querySelectorAll(".individualUsers");
for (var i = 0; i < btnUser.length; i++) {
btnUser[i].addEventListener("click", function() {
var clickedUser = this.innerText
var userBooks = books
.filter(x => x.users.name.indexOf(clickedUser) > -1)
.map(x => ` <li>${x.title}</li> <li>${x.author}</li>`);
console.log(clickedUser);
});
}
My problem is x.users.name.indexOf(clickedUser)is not accessing the user name.
You need to search inside the users array as well, one neat way is to do so with Array.some that return true if some of the conditional is true.
const books = [{
"title": "title1",
"author": "author1",
"users": [{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
}
];
const clickedUser = 'Jose Miguel';
var userBooks = books
.filter(x => x.users.some(user => user.name.indexOf(clickedUser) > -1));
console.log(userBooks);
I have 2 objects, a course list and a user.
The course list is an array with a lot of courses:
[
{
"id": 12345,
"title": "Some title",
"type": [
{
"id": 4700,
"slug": "someType",
"name": "someTypeName"
}
],
"difficulty": [
{
"id": 4704,
"slug": "4",
"name": "hard"
}
],..
},
{...}
The user have also some fields:
{
"difficulty": 4, // the difficulty->slug
"type": "someType" // the type->slug
}
My task:
I want to find the best match between the courses and the user.
In this example the user is looking for type.slug == someType and a difficulty.slug == 4. The slug is always the search term.
My first attempt was:
courseList.filter((course) => {
if (course.type.indexOf(that.userData.type) != -1) {
return course; // dont work
}
});
Edit: I need to display the name and the id properties in the front-end and the "slug" is always the search term.
The filter function takes a function (in your case the arrow function) that returns a boolean so try this instead:
var filterredList = courseList.filter(course => {
return course.type.filter(type => type.slug == that.userData.type).length > 0
&& course.difficulty.filter(difficulty => difficulty.slug == that.userData.difficulty).length > 0
});
You need to compare the slug properties against the user data.
The trick here is to make sure you are filtering the arrays and checking the count.
var courseList = [
{
"id": 12345,
"title": "Some title",
"type": [
{
"id": 4700,
"slug": "someType",
"name": "someTypeName"
}
],
"difficulty": [
{
"id": 4704,
"slug": "4",
"name": "hard"
}
]
},
{
"id": 12346,
"title": "Another title",
"type": [
{
"id": 4701,
"slug": "anotherType",
"name": "anotherTypeName"
}
],
"difficulty": [
{
"id": 4704,
"slug": "4",
"name": "hard"
}
]
}
];
var userData = {
type: 'someType',
difficulty: 4
};
var filteredList = courseList.filter(o =>
o.type.filter(t => t.slug === userData.type).length > 0
&& o.difficulty.filter(d => d.slug === userData.difficulty.toString()).length > 0
);
// Print just the titles of the filtered list
console.log(filteredList.map(o => o.title));