Search objects for a given string - javascript

I have these objects
const data = [
{
id: 1,
recipient: "001",
assessment: "Apta",
score: "2",
ovarian: "E1",
},
{
id: 2,
recipient: "ABC2",
assessment: "Apta",
score: "2,5",
ovarian: "E1",
},
{
id: 3,
recipient: "003",
assessment: "Refugo",
score: "3",
ovarian: "E1",
},
{
id: 4,
recipient: "004",
assessment: "Apta",
score: "4",
ovarian: "E2",
},
];
And this is my code, which when it finds the correct string it returns me:
const searchAnimal = value => {
setInput(value);
JSON.parse(records).filter(item => {
if (item.recipient === value) {
setSearch([item]);
}
});
};
What would the logic be to return all object.recipients that start with 00? Would a regex maybe do it?

I think changing a little bit the logic would help:
let search = function (data, searchString) {
return data.filter((item) => {
return item.recipient.includes(searchString);
});
};
By doing so will give you the object you're searching for.

You can filter for the objects with a recipient that starts with 00 by using:
const array00Animals = data.filter((animal) => animal.recipient.substr(0, 2) === '00');
This will return the array of objects but only id's 1, 3 and 4 from your sample data.

Related

Could use someone's expertise with filtering my nested array by a certain value

I know there are a ton of "How to filter my array" questions. However, I'm still stuck.
I'm not too familiar with arrays and I'm hoping someone can help me with my particular situation.
I have an array that I'm trying to filter. I'm looking to return all data if "user.name" or "writers.name" equals "Adam". "user" will only ever have one name, while "writers" can have multiple.
[{
mediaId: '86699',
user: {
name: 'Adam',
id: '17622'
},
nodeType: 'testNode',
title: 'testTitle',
id: '23968',
writers: []
},
{
mediaId: '90547',
user: {
name: 'Jake',
id: '65936'
},
nodeType: 'testNode',
title: 'testTitleTwo',
id: '89960',
writers: [{
name: 'Adam',
id: '17622'
},
{
name: 'Steve',
id: '47622'
}]
},
{
mediaId: '99662',
user: {
name: 'James',
id: '22236'
},
nodeType: 'testNode',
title: 'testTitleThree',
id: '89960',
writers: [{
name: 'Paul',
id: '27622'
}]
}
]
Desired output:
[{
"mediaId": "86699",
"user": {
"name": "Adam",
"id": "17622"
},
"nodeType": "testNode",
"title": "testTitle",
"id": "23968",
"writers": []
},
{
"mediaId": "90547",
"user": {
"name": "Jake",
"id": "65936"
},
"nodeType": "testNode",
"title": "testTitleTwo",
"id": "89960",
"writers": [{
"name": "Adam",
"id": "17622"
},
{
"name": "Steve",
"id": "45389"
}]
}
]
Thank you in advance!!!
UPDATED: Everything is the same except that user and writers are now wrapped around properties.
[{
mediaId: '86699',
nodeType: 'testNode',
title: 'testTitle',
id: '23968',
properties: {
user: {
name: 'Adam',
id: '17622'
},
writers: []
}
}, {
mediaId: '90547',
nodeType: 'testNode',
title: 'testTitleTwo',
id: '89960',
properties: {
user: {
name: 'Jake',
id: '65936'
},
writers: [{
name: 'Adam',
id: '17622'
}, {
name: 'Steve',
id: '47622'
}]
}
}, {
mediaId: '99662',
nodeType: 'testNode',
title: 'testTitleThree',
id: '89960',
properties: {
user: {
name: 'James',
id: '22236'
},
writers: [{
name: 'Paul',
id: '27622'
}]
}
}]
To apply a filter, you are essentially iterating over each item in the array and seeing if it matches your criteria. Return true if you want it to stay, and return false if you want it to be filtered out.
So at the top-most layer, you have an array of objects, each of which appears to represent a node (judging by the "nodeType" property). We start with this:
const matches = array.filter(node => {
// criteria go here
return true; // or false
});
What are the criteria? Well it should remain if...
The node.user.name is "Adam"
Of the writers, at least one has writer.name === "Adam"
Let's define those.
const hasUserNameAdam = (node) => node?.user?.name === "Adam";
const hasWriterNameAdam = (writer) => writer?.name === "Adam";
We can do the same thing with the writer array to handle the second layer.
const arrayHasWriterNameAdam = writerArray.some(writer => hasWriterNameAdam(writer));
Now we just need to plug them in.
const matches = data.filter(node => {
const hasUserNameAdam = (node) => node?.user?.name === "Adam";
const hasWriterNameAdam = (writer) => writer?.name === "Adam";
const arrayHasWriterNameAdam = (writerArray) => writerArray.some(writer => hasWriterNameAdam(writer));
return hasUserNameAdam(node) || arrayHasWriterNameAdam(node?.writers);
});
And we can choose to refactor those inner functions back to being in line to clean things up, if we would like.
const matches = data.filter(node => node?.user?.name === "Adam" || node?.writers?.some(writer => writer?.name === "Adam"));
Update
Or with the updated object shape, the user and writers props are nested under the properties prop, so we only have to add the .properties layer to everywhere we access the user and writers properties to adapt.
const matches = data.filter(node => node?.properties?.user?.name === "Adam" || node?.properties?.writers?.some(writer => writer?.name === "Adam"));
input.filter(element => element.user.name === 'Adam' || element.writers.some(writer => writer.name === 'Adam'));
Try this:
const findAdam = arr => arr.filter(
element => element.properties.user.name === 'Adam' || element.properties.writers.some(writer => writer.name === 'Adam')
)

filtered by name using node js

Is there any way i can filter files with given extension and then further filter them
for eg: I have .txt extension and i want to get all my .txt from an array
file=
[ "animal_bio.txt",
"xray.pdf",
"fish_bio.txt",
"mammal_doc.txt",
"human_bio.txt",
"machine.jpg"
]
filtered output contain all .txt extension and further it should contain all the files which have _bio.txt name in it.
so output look like
futherFile=
[ "human_bio.txt",
"fish_bio.txt",
"animal_bio.txt"
]
You can use String.protytype.endsWith function to compare the strings with your extension
const file =
[ "animal_bio.txt",
"xray.pdf",
"fish_bio.txt",
"mammal_doc.txt",
"human_bio.txt",
"machine.jpg"
]
result = file.filter((fileName) => fileName.endsWith("_bio.txt"));
console.log(result)
You can use the Array.filter method and use the String.endsWith method to filter. An example -
// List of files
file = ["animal_bio.txt",
"xray.pdf",
"fish_bio.txt",
"mammal_doc.txt",
"human_bio.txt",
"machine.jpg"
]
// Filtering by extension
file.filter(x => x.endsWith(".txt"));
Hope it helped :)
You can easily achieve this result using reduce and match
When matching for the doc or bio, You can even restrict more to get the string only if _doc.txt is at end of the string using Regular expression /_bio.txt$/
const arr = [
{
id: "1",
name: "animal_bio.txt",
},
{
id: "2",
name: "xray.pdf",
},
{
id: "3",
name: "animal_doc.txt",
},
{
id: "4",
name: "fish_doc.txt",
},
{
id: "5",
name: "flower_petals.jpg",
},
{
id: "5",
name: "plant_roots.jpg",
},
{
id: "6",
name: "human_image.jpg",
},
{
id: "7",
name: "human_bio.txt",
},
{
id: "8",
name: "mammal_doc.txt",
},
];
const result = arr.reduce((acc, { name }) => {
if (name.match(/\.txt$/)) {
if (name.match(/_bio/)) {
acc[0].push(name);
} else {
acc[1].push(name);
}
}
return acc;
},
[[], []]
);
console.log(result);
Then you can get the element containing doc and bio using array destructuring as
const [bioArr, docArr] = result;
console.log(bioArr);
console.log(docArr);
const arr = [
{
id: "1",
name: "animal_bio.txt",
},
{
id: "2",
name: "xray.pdf",
},
{
id: "3",
name: "animal_doc.txt",
},
{
id: "4",
name: "fish_doc.txt",
},
{
id: "5",
name: "flower_petals.jpg",
},
{
id: "5",
name: "plant_roots.jpg",
},
{
id: "6",
name: "human_image.jpg",
},
{
id: "7",
name: "human_bio.txt",
},
{
id: "8",
name: "mammal_doc.txt",
},
];
const result = arr.reduce(
(acc, { name }) => {
if (name.match(/\.txt$/)) {
if (name.match(/_bio/)) {
acc[0].push(name);
} else {
acc[1].push(name);
}
}
return acc;
},
[[], []]
);
const [bioArr, docArr] = result;
console.log(bioArr);
console.log(docArr);
you can use filter function from ES6 like:
const txtFile = file.filter((item) => (item.split('_'))[1] === 'bio.txt')

Javascript compare two JSON arrays and return key of the unmatched value

I have two JSON arrays, would like to know the key which don't match. I don't need the value.
Example:
livetable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" },
],
backupTable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" },
],
I can get the key/value pair which is diffrent with this Lodash script:
difference = _.differenceWith(livetable,backupTable,_.isEqual)
But I would just need the key, in this example "name" for "id: 2" is not matching, so I would need to get the "name" key to new array/variable.
(Using VUE CLI)
EDIT: Added example of current code output.
var livetable = [{"id": 1, "name": "Sandra", "id": 2, "name": "John"}]
var backupTable = [{"id": 1, "name": "Sandra", "id": 2, "name": "Peter"}]
console.log(_.differenceWith(backupTable,livetable,_.isEqual))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
This will output the key:value pair, but I would just need the key which is diffrent.
I think I understand what you're trying to do. There are some unknowns though, like what should happen if there is a missing record in the second data set?
This solution assumes each table of data has the same amount of records and the records have the same IDs.
// define data
const livetable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" }
]
const backupTable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" }
]
const getDifferentRecordsByID = (sourceRecords, compareRecords) => {
// simple utility function to return a record object matching by ID
const findComparisionRecord = id => compareRecords.find(compareRecord => compareRecord.id === id)
// using the utility function, we can filter out any mismatching records by comparing name
return sourceRecords
.filter(sourceRecord => sourceRecord.name !== findComparisionRecord(sourceRecord.id).name)
// then map over all the records and just pull out the ID
.map(record => record.id)
}
console.log(getDifferentRecordsByID(livetable, backupTable)) // [2]
Here is working VUE code for my problem.
Function returns [ "name" ], which is exactly what I need.
data() {
return {
livetable: [{ id: 1, name: "Sandra" },{ id: 2, name: "John" }],
backupTable: [{ id: 1, name: "Sandra" },{ id: 2, name: "Peter" }],
difColumns: null,
};
},
methods: {
test3() {
let resultArray = []
this.livetable.forEach((array1, index) => {
const array2 = this.backupTable[index];
resultArray.push(this._.reduce(array1, (result, value, key) => this._.isEqual(value, array2[key]) ? result : result.concat(key), []))
});
this.difColumns = resultArray[0]
}
},

Removing properties from JSON response

I have this JSON (as a string):
[{"product":{"id":"25","age":"35","name":"hp keyboard"},"quantity":1},
{"product":{"id":"9","age":"25","name":"lenovo hero"},"quantity":2}]
How can delete or remove all id & age properties (with their value) from the array of objects, so I can get new array out of it?
You seem to have an array with two JSON strings, but as you present them in your question they are not valid.
I'll assume your array is in fact like this -- run the snippet to see how many backslashes really need to be there:
let jsons = [
JSON.stringify({ product: { id: "25", age:"35", name: "hp keyboard" }, quantity: 1 }),
JSON.stringify({ product: { id: "9", age:"25", name: "lenovo hero" }, quantity: 2 })
];
console.log(jsons);
You should ask yourself why you stick with JSON, and do not just parse them, and then continue without JSON. But, given that you have JSON there, here is how you can remove the two said properties:
let jsons = [
JSON.stringify({ product: { id: "25", age:"35", name: "hp keyboard" }, quantity: 1 }),
JSON.stringify({ product: { id: "9", age:"25", name: "lenovo hero" }, quantity: 2 })
];
let jsons2 = jsons.map(json => {
let { product: { id, age, ...restProduct }, ...rest } = JSON.parse(json);
return JSON.stringify({ product: restProduct, ...rest });
});
console.log(jsons2);
Note how first the JSON is parsed, then a new object is created that lacks the two properties, and finally that is converted back to JSON again.
If you want to only keep some specific properties ("white list") in a flat (non-nested JSON, then proceed like this:
let jsons = [
JSON.stringify({ product: { id: "25", age:"35", name: "hp keyboard" }, quantity: 1 }),
JSON.stringify({ product: { id: "9", age:"25", name: "lenovo hero" }, quantity: 2 })
];
let jsons2 = jsons.map(json => {
let { product: { id, age }, quantity } = JSON.parse(json);
return JSON.stringify({ id, age, quantity });
});
console.log(jsons2);
In case your input is not an array (as hinted in your comments below), but a JSON string as a whole, then proceed as follows:
let json = JSON.stringify([
{ product: { id: "25", age:"35", name: "hp keyboard" }, quantity: 1 },
{ product: { id: "9", age:"25", name: "lenovo hero" }, quantity: 2 }
]);
let json2 = JSON.stringify(
JSON.parse(json).map(({ product: { id, age }, quantity }) =>
({ id, age, quantity })
)
);
console.log(json);
Just iterate over the array using Array.prototype.forEach and delete the unwanted properties:
const arr = [{
"product": {
"id": "25",
"age": "35",
"name": "hp keyboard"
},
"quantity": 1
},
{
"product": {
"id": "9",
"age": 25,
"name": "lenovo hero "
},
"quantity ": 2
}
]
const newArr = JSON.parse(JSON.stringify(arr)); // deep clone arr
newArr.forEach(function(arrEl) {
delete arrEl.product.id;
delete arrEl.product.age
});
console.log(arr); // old array unchanged
console.log(newArr); // new Array with deleted properties

Map value of an attribute in one object array to an attribute in another object array Javascript

I have two arrays of objects:
courses = [ { _id: 999, courseCode: "Eng1" },
{ _id: 777, courseCode: "Sci1" },
{ _id: 666, courseCode: "Eng2" },
{ _id: 888, courseCode: "Sci2" } ]
sectionCourses = [ { sectionCode: "1A", courseId: "999" },
{ sectionCode: "1A", courseId: "777" },
{ sectionCode: "2A", courseId: "666" },
{ sectionCode: "2A", courseId: "888" } ]
I want to filter the courses array in such a way that it contains only the courses that are not in a section.
For example if I select section with sectionCode: "2A", the courses array should only contain
courses = [ { _id: 999, courseCode: "Eng1" },
{ _id: 777, courseCode: "Sci1" },
{ _id: 888, courseCode: "Sci2" } ]
I tried to do this way:
courses = courses.filter(c => !(sectionCourses.includes(c._id)))
but I know this is incomplete because I can't figure out how to access courseId in sectionCourses.
Please help.
You can't use .includes() method to find the whole object by its _id, includes compares the whole objects and doesn't search for a specific property.
What you can do here is to get an array of courseIds to be ignored based on the sectionCode you provided, and then filter the courses that their _id doesn't exist in this array of ids:
function getCourses(catCode) {
var coursesIdstoIgnore = sectionCourses.filter(s => s.sectionCode === catCode).map(s => s.courseId);
return courses.filter(c => coursesIdstoIgnore.indexOf(c["_id"].toString()) == -1);
}
Demo:
var courses = [{
_id: 999,
courseCode: "Eng1"
},
{
_id: 777,
courseCode: "Sci1"
},
{
_id: 666,
courseCode: "Eng2"
},
{
_id: 888,
courseCode: "Sci2"
}
];
var sectionCourses = [{
sectionCode: "1A",
courseId: "999"
},
{
sectionCode: "1A",
courseId: "777"
},
{
sectionCode: "2A",
courseId: "666"
},
{
sectionCode: "2A",
courseId: "888"
}
];
function getCourses(catCode) {
var cousesIdstoIgnore = sectionCourses.filter(s => s.sectionCode === catCode).map(s => s.courseId);
console.log(cousesIdstoIgnore);
return courses.filter(c => cousesIdstoIgnore.indexOf(c["_id"].toString()) == -1);
}
var results = getCourses("2A");
console.log(results);
courses.filter(course => sectionCourses.find(section => +section.courseId === +course._id))
Note how i use the +operator before of the courseId and _id properties. this automatically turns a String typed number into a Number.
e.g
+"1" = 1
+1 = 1
This is very useful for slight comparison gotchas when using ===
Note Array.find() doesn't work with IE

Categories

Resources