Find a specific object in an array of objects - javascript

I don't understand because I use the method "find" but I get "undefined"...
My data :
[
{ "id": 2, "title": "My project", "nameStructure": "Entreprise", "studies":
[
{"id": 3, "name": "My stidue", "status": "in prepa" },
{ "id": 4, "name": "My second study ", "status": "In"}
],
"typeStructure": "Entreprise"
},
{ "id": 3, "title": "My project 2", "nameStructure": "Entreprise 2", "studies":
[
{"id": 4, "name": "My stidue 2", "status": "in prepa" },
{ "id": 5, "name": "My second study 2 ", "status": "In"}
],
"typeStructure": "Entreprise 2"
},
...
]
I would like to have only the object with the ID 2 for example.
So I wrote :
const id = 2
myarray.filter(p => p.id === id);
But it does not work... I always get "undefined"
Thanks for help

ID is a number, therefore you need to remove the quotes around 2
myarray.filter(p => p.id === 2);
and the operator === in Javascript means that 2 should be equal to "2" as in value and type
reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality

const arr = [
{
id: 2,
title: "My project",
nameStructure: "Entreprise",
studies: [
{ id: 3, name: "My stidue", status: "in prepa" },
{ id: 4, name: "My second study ", status: "In" }
],
typeStructure: "Entreprise"
},
{
id: 3,
title: "My project 2",
nameStructure: "Entreprise 2",
studies: [
{ id: 4, name: "My stidue 2", status: "in prepa" },
{ id: 5, name: "My second study 2 ", status: "In" }
],
typeStructure: "Entreprise 2"
}
];
const newItem = arr.find((item) => item.id === 2);
console.log("newItem>>>>", newItem);

Related

How to reformat object using its property value as property key?

how can I assign object property value as property key?
I have a set of data:
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
]
I want to reformat it to become:
const mydata = [
{
"Title 1": "Value 1"
},
{
"Title 2": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
]
},
]
I have tried this code to achieve it:
mydata.map((dt: any) => {
dt.title: dt.value
});
However, it seems not working.
Any idea how can I reformat it to the one I desire?
Thanks.
Please use following code.
Reference URL How to use a variable for a key in a JavaScript object literal?
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
let reData = [];
mydata.forEach((dt)=>{
reData.push({[dt.title]: dt.value});
});
console.log(reData);
If you want to transform the array to a different type of variable, use [reduce][1]
const mydata = [
{
id: 001,
value: "Value 1",
title: "Title 1",
},
{
id: 002,
value: [
{
Name: "Name 1",
Age: "20",
},
{
Name: "Name 2",
Age: "30",
},
],
title: "Title 2",
},
];
const data = mydata.reduce(
(acc, cur) => ({ ...acc, [cur.title]: cur.value }),
{}
);
console.log(data);
Your map function has an error, and your key assignment has another one. Let's fix it.
const newData = mydata.map((dt: any) => ({
[dt.title]: dt.value,
}));
First: You can't return an object from an arrow function without parenthesis, if you don't use it, the code will think it is a function body not an object.
Second: If you want to return a value as a key, you need put it inside "[ ]" (Square brackets)
Just that, simple mistakes, at the end you came up with the right logic to solve it
Add brackets around the return value.
Use square brackets for a computed property name.
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
const res = mydata.map(({value, title})=>({[title]: value}));
console.log(res);

Filter inside a nested array with objects

I have an array that contains three book objects. Each book object has an array of bookIds . I want to filter by bookId (3,1) in a fast and efficient way since my array will grow up easly in the future. I tried with map, but it change my original array even with a deepCopy ! Is there a way to use the filter function instead without using recursivity ?
this.booksList =
[
{
"books": [
{
"bookId": 3
},
{
"bookId": 2
}
],
"id": 1,
"name": "Name 1",
"description": "desc 1"
},
{
"books": [
{
"bookId": 5
},
{
"bookId": 2
}
],
"id": 2,
"name": "Name 2",
"description": "desc 2"
},
{
"books": [
{
"bookId": 1
},
{
"bookId": 3
}
],
"id": 3,
"name": "Name 3",
"description": "desc 3"
}
]
The map approach :
let results = this.books.map(function (book) {
book.books = book.books.filter(x => x.bookId == 1 || x.bookId == 3);
return book;
}).filter(({ books }) => books.length);
Result with map : not expected result !
[
{
"books": [
{
"bookId": 3
}
],
"id": 1,
"name": "Name 1",
"description": "desc 1"
},
{
"books": [
{
"bookId": 1
},
{
"bookId": 3
}
],
"id": 3,
"name": "Name 3",
"description": "desc 3"
}
]
expected results :
[
{
"books": [
{
"bookId": 3
},
{
"bookId": 2
}
],
"id": 1,
"name": "Name 1",
"description": "desc 1"
},
{
"books": [
{
"bookId": 1
},
{
"bookId": 3
}
],
"id": 3,
"name": "Name 3",
"description": "desc 3"
}
]
Thanks,
I think you are looking for filter and some -
const input =
[{books:[{bookId:3},{bookId:2}],id:1,name:"Name 1",description:"desc 1"},{books:[{bookId:5},{bookId:2}],id:2,name:"Name 2",description:"desc 2"},{books:[{bookId:1},{bookId:3}],id:3,name:"Name 3",description:"desc 3"}]
const query =
[3, 1]
const result =
input.filter(({ books = [] }) =>
books.some(({ bookId = null }) => query.includes(bookId))
)
console.log(JSON.stringify(result, null, 2))
Output -
[
{
"books": [
{
"bookId": 3
},
{
"bookId": 2
}
],
"id": 1,
"name": "Name 1",
"description": "desc 1"
},
{
"books": [
{
"bookId": 1
},
{
"bookId": 3
}
],
"id": 3,
"name": "Name 3",
"description": "desc 3"
}
]
const booksList=[
{books:[{bookId:3},{bookId:2}],id:1,name:"Name 1",description:"desc 1"},
{books:[{bookId:5},{bookId:2}],id:2,name:"Name 2",description:"desc 2"},
{books:[{bookId:1},{bookId:3}],id:3,name:"Name 3",description:"desc 3"},
];
const byBookIDs = (...IDs) =>
booksList.filter(b => b.books.some(b => IDs.includes(b.bookId)));
console.log(byBookIDs(1, 3));
MDN Array Filter - to return a subset
MDN Array Some - to match (and return) as soon as some
MDN Array Includes - to find item in array

Map new object from two objects array angular typescript baesed on id

I have something like this
export class Question {
id: string;
title: string;
description: string;
answers: Answer[];
}
export class Answer {
id: string;
text: string;
questionId: string;
}
and I have two object like this
answers = [
{
"id": 1,
"text": "some comment1",
"questionId": 1
},
{
"id": 2,
"text": "some comment2",
"questionId": 3
},
{
"id": 3,
"text": "some comment3",
"questionId": 3
}
];
questions = [
{
"id": 1,
"title": "Name1",
"description": "typicode1"
},
{
"id": 2,
"title": "Name2",
"description": "typicode2"
},
{
"id": 3,
"title": "Name3",
"description": "typicode3"
}
];
questionsAndAnswers: Question[];
Now i need to map answer to correct question on property answers
My new questionsAndAnswers should look like this
questionsAndAnswers = [{
id: 1,
title: Name1,
description: typicode1;
answers: [{
"id": 1,
"text": "some comment1",
"questionId": 1
}]
},
{
id: 2,
title: Name2,
description: typicode2;
answers: []
},
{
id: 3,
title: Name3,
description: typicode3;
answers: [{
"id": 2,
"text": "some comment2",
"questionId": 3
},
{
"id": 3,
"text": "some comment3",
"questionId": 3
}]
}
];
You could try use Array reduce with filter function. Try the following
var questions = [ { "id": 1, "title": "Name1", "description": "typicode1" }, { "id": 2, "title": "Name2", "description": "typicode2" }, { "id": 3, "title": "Name3", "description": "typicode3" } ];
var answers = [ { "id": 1, "text": "some comment1", "questionId": 1 }, { "id": 2, "text": "some comment2", "questionId": 3 }, { "id": 3, "text": "some comment3", "questionId": 3 } ];
var questionsAndAnswers = questions.reduce((acc, curr, index) => {
acc[index] = curr;
acc[index].answers = answers.filter(answer => answer.questionId === curr.id);
return acc;
}, []);
console.log(questionsAndAnswers);

compare two arrays of objects and return the item

I have an object array that looks something like this:
let products = [
{
"id": 7,
"name": "product 1",
"description": "description product 1",
"images": [
{
"id": 1,
"path": "image1-product1.jpeg",
},
{
"id": 2,
"path": "image2-product1.jpeg",
}
]
},
{
"id": 20,
"name": "product 2",
"description": "description product 2",
"images": [
{
"id": 3,
"path": "image1-product2.jpeg",
},
{
"id": 4,
"path": "image2-product2.jpeg",
}
]
}
]
Each product has an image array, I need to compare this image arrangement, with one that I will receive as a parameter and that will look exactly like one of them, to know which product it belongs to and return that product.
for example if I receive this array:
[
{
"id": 3,
"path": "image1-product2.jpeg",
},
{
"id": 4,
"path": "image2-product2.jpeg",
}
]
equals the images array of product 2, so how can I compare these and return that product?
If comparing by the id is sufficient, using Array.prototype.every() is a lot more efficient than using JSON.stringify():
const productHasImages = images => product => (
product.images.length === images.length &&
product.images.every(
(image, i) => image.id === images[i].id
)
);
const products = [{ id: 7, name: 'product 1', description: 'description product 1', images: [{ id: 1, path: 'image1-product1.jpeg' }, { id: 2, path: 'image2-product1.jpeg' }] }, { id: 20, name: 'product 2', description: 'description product 2', images: [{ id: 3, path: 'image1-product2.jpeg' }, { id: 4, path: 'image2-product2.jpeg' }] }];
const images = [{ id: 3, path: 'image1-product2.jpeg' }, { id: 4, path: 'image2-product2.jpeg' }];
const product = products.find(productHasImages(images));
console.log(product);
If you want to match regardless of order and you need to compare multiple properties, then you'll need to be a bit more clever by initializing a Map keyed by id in the closure:
const productHasImages = images => {
const map = new Map(
images.map(image => [image.id, image])
);
return product => (
product.images.length === images.length &&
product.images.every(
({ id, path }) => {
const image = map.get(id);
if (!image) return false;
// compare other properties here
return image.path === path;
}
)
);
};
const products = [{ id: 7, name: 'product 1', description: 'description product 1', images: [{ id: 1, path: 'image1-product1.jpeg' }, { id: 2, path: 'image2-product1.jpeg' }] }, { id: 20, name: 'product 2', description: 'description product 2', images: [{ id: 3, path: 'image1-product2.jpeg' }, { id: 4, path: 'image2-product2.jpeg' }] }];
// in different order
const images = [{ id: 4, path: 'image2-product2.jpeg' }, { id: 3, path: 'image1-product2.jpeg' }];
const product = products.find(productHasImages(images));
console.log(product);
If order does not matter and the assumption can be made that all the id and path match and need to be exact... Then you can just compare the stringify of each array. If you need to more relaxed comapre then you have to loop even more into the arrays and compare individual values.
let products = [
{
"id": 7,
"name": "product 1",
"description": "description product 1",
"images": [
{
"id": 1,
"path": "image1-product1.jpeg",
},
{
"id": 2,
"path": "image2-product1.jpeg",
}
]
},
{
"id": 20,
"name": "product 2",
"description": "description product 2",
"images": [
{
"id": 3,
"path": "image1-product2.jpeg",
},
{
"id": 4,
"path": "image2-product2.jpeg",
}
]
}
]
let incoming = [
{
"id": 3,
"path": "image1-product2.jpeg",
},
{
"id": 4,
"path": "image2-product2.jpeg",
}
]
let result = null
result = products.find(product => {
return JSON.stringify(product.images) === JSON.stringify(incoming)
})
console.log(result)
If I understood right. You will get an object containing an id and a image. This object is inside one of the products images somewhere, and you want to find/return the product that holds this image?
If so, you can combine the .find array prototype to find the object passing the condition (one of the images being the one you provide)
let products = [{
"id": 7,
"name": "product 1",
"description": "description product 1",
"images": [{
"id": 1,
"path": "image1-product1.jpeg",
},
{
"id": 2,
"path": "image2-product1.jpeg",
}
]
},
{
"id": 20,
"name": "product 2",
"description": "description product 2",
"images": [{
"id": 3,
"path": "image1-product2.jpeg",
},
{
"id": 4,
"path": "image2-product2.jpeg",
}
]
}
]
const compare = (imageObjToFind) => {
return products.find(product => product.images.find(image => JSON.stringify(image) === JSON.stringify(imageObjToFind)))
}
const IwantToCompareThis = {
"id": 4,
"path": "image2-product2.jpeg",
}
console.log(compare(IwantToCompareThis))

Ramda to loop over array

Loop may be the wrong term, but it kind of describes what I am attempting.
I want to give structure to flat data, but I also need to keep track of the array it came from.
Basically my rules are (per array):
If level 1 exists- give it the name of the item, and a typechild array. EACH time a level 1 appears (even in the same array) it should create a new entry.
Inside typechild, put the any items with level >1
If NO level 1 exists- give it the name of the item, and a typechild array.
My code below is almost there, with the exception that it should create an array EVERYTIME it sees a level 1. My example will make sense:
Input data
[
{
"title": "Test 1",
"type": [{
"name": "Animal",
"level": 1
},
{
"name": "Food",
"level": 1
},
{
"name": "Chicken",
"level": 3
}
]
},
{
"title": "Test 2",
"type": [{
"name": "Foo",
"level": 2
}]
}
]
Note: Animal and Food are both LEVEL 1 items. So it should create two ARRAYS like so...
Desired output
[
{
name: "Animal",
typechild: [
{
level: 2,
name: "Chicken"
}
]
},
{
name: "Food",
typechild: [
{
level: 2,
name: "Chicken"
}
]
},
{
name: "NoName",
typechild: [
{
level: 2,
name: "Foo"
}
]
}
]
Ramda attempt (try here: https://dpaste.de/JQHw):
const levelEq = (n) => pipe(prop('level'), equals(n));
const topLevel = pipe(prop('type'), find(levelEq(1)));
const topLevelName = pipe(topLevel, propOr('NoName', 'name'));
const extract2ndLevel = pipe(pluck('type'), flatten, filter(levelEq(2)));
const convert = pipe(
groupBy(topLevelName),
map(extract2ndLevel),
map(uniq),
toPairs,
map(zipObj(['name', 'typechild']))
);
Something like this?
var output = [{
"name": "Animal",
"typechild": [{
"name": "Chicken",
"level": 3
}, {
"name": "Dog",
"level": 2
}]
}, {
"name": "Food",
"typechild": [{
"name": "Chicken",
"level": 3
}]
}, {
"name": "No name",
"typechild": [{
"name": "Foo",
"level": 2
}, {
"name": "Baz",
"level": 2
}]
}]
let out = {},
typechild = {},
k;
const data = [{
"title": "Test 1",
"type": [{
"name": "Animal",
"level": 1
}, {
"name": "Food",
"level": 1
}, {
"name": "Chicken",
"level": 3
}]
}, {
"title": "Test 2",
"type": [{
"name": "Foo",
"level": 2
}]
}, {
"title": "Test 3",
"type": [{
"name": "Baz",
"level": 2
}]
}, {
"title": "Test 4",
"type": [{
"name": "Animal",
"level": 1
}, {
"name": "Dog",
"level": 2
}]
}]
data.forEach((node) => {
k = false;
typechild[node.title] = [];
node.type && node.type.forEach((t, i) => {
if (t.level == 1) {
k = true;
!out[t.name] ? out[t.name] = {
name: t.name,
typechild: typechild[node.title]
} : out[t.name].typechild = out[t.name].typechild.concat(typechild[node.title]);
} else {
typechild[node.title].push(t);
}
if (i == node.type.length - 1 && !k && typechild[node.title].length) {
out['No name'] = out['No name'] || {
name: 'No name',
typechild: []
};
out['No name'].typechild = out['No name'].typechild.concat(typechild[node.title]);
}
});
});
console.log(JSON.stringify(Object.values(out)));

Categories

Resources