append array by index in nested array of object - javascript

I created a sample code to demo my problem, the actual data is much bigger
const arr = [{
id: 1
}, {
id: 2,
items: [{
id: 1
}]
}]
const target = 2
const nextIndex = 1
newArr = arr.map(o => o.id === target ? ({
...o,
items: [...o.items, {
id: 'new id'
}]
}) : o);
console.log(newArr);
How to insert {id: 'new id'} by index? Above code is appending onto items array. Assuming I have a click event, user can insert the position of {id: 'new id} by index, I can't use append as it doesn't replace existing object.
expected output
[{
id: 1
}, {
id: 2,
items: [{
id: 1
},{
id: 'something'
}]
Above code doesn't work, adding new item to items array without using index.

Try to pass index from onClick event
functionName = (i) => { //where i is index from onclick event
arr.map( o, index) => {
if(i === index)
{
const obj = { //object
id: 'new id'
}
arr[i].push(obj) // push object at given index from onClick
}
}
}

The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements
const target = 2;
int index = arr.findIndex(v => v.id == target);
if (index > -1) {
arr.splice(index, 1, {id: 'new id'}); // replace 1 with 0 if you just want to insert.
}

Related

Changing a value inside the array in a forEach() loop

Message: This is a function I'm going to implement in my very first project (Which is a point-of-sale system) using Vue Js and I wrote this function using pure JavaScript to simplify this question. So I'd be really grateful if somebody could help me with this problem so I can continue building my practice project. Thanks ❤️
My code explanation: I have an empty array called newArray.And an array called mainArray with some records. And I've included a button with an onClick event that triggers the function clicked() with an argument passed to it, which is 2 in this case.
What I'm expecting to get: I want to check for a record inside the newArray which contains an id with 2. If such a record is found, I want to add the stock value by 1 in the record. If such a record is not found inside the newArray loop through the mainArray and copy the record which has the id of 2 and add it to the newArray and reset the stock to 1 (So when we click the button again, the record which has id 2 is already there inside the newArray, therefore, I want to add 1 to it, So the stock: 2 now). I have attempted on this problem, and I have attached the code.
Summary according to my project: I have looped through mainArray in my project, so each record has a button with clicked() function, with an attribute called productId, productId is passed as the argument to the clicked() function, I'm expecting: If I click on a button it takes productId as the argument and the function loops through the newArray finding for a record which has id equal to the productId If such record is there add stock by 1. If such record is not there grab the record from the mainArray which has the id equal to the productId value and put inside the newArray by setting the stock value to 1 (stock: 1). So when I click the same button which has the same attribute value it will add 1 to the stock in the record of the same value equal to the id inside the newArray (therefore the stock: 2 now) If again click stock will be stock: 3 so on adding by 1.
function clicked(inp){
const newArray = [];
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
newArray.forEach((item) => {
if(inp == item.id){
item.days = item.days + 1;
} else {
mainArray.forEach((element) => {
if(inp == element.id){
newArray.push(element);
}
});
}
});
console.log(newArray);
}
<button id="1" onClick="clicked(2)">Click me</button>
Suggestion : move newArray outside the clicked function as it is going to update on click.
Implementation : You can use Array.filter() method on newArray to check if record as per the input id is available or not and then by using Array.find() you can do filtering on the mainArray if there is no data in newArray.
Live demo :
const newArray = [];
function clicked(inp){
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const findInNewArr = newArray.filter(item => inp === item.id);
if (findInNewArr.length) {
newArray[0].stock += 1;
} else {
const findInMainArray = mainArray.find(element => inp === element.id);
if (findInMainArray) {
findInMainArray.stock = 1;
newArray.push(findInMainArray);
}
}
console.log(newArray);
}
<button id="1" onclick="clicked(2)">Click me</button>
This is what I really expected (Thanks to Rohìt Jíndal for giving me the idea of doing this)
const newArray = [{ id: 1, name: "Shoes",stock: 1, price: 10 }];
function clicked(inp){
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const findInNewArr = newArray.filter(item => inp === item.id);
if (findInNewArr.length > 0) {
newArray.forEach((element) => {
if(element.id === inp) {
element.stock += 1;
}
});
} else {
const findInMainArray = mainArray.find(element => inp === element.id);
if (findInMainArray) {
findInMainArray.stock = 1;
newArray.push(findInMainArray);
}
}
console.log(newArray);
}
<button id="1" onclick="clicked(2)">Click me</button>
In your code forEach function will not be executed, because newArray is empty, so there is nothing to iterate through.
You might use findIndex to loop through newArray and then check if index is greater than -1. That would mean that array contains object with specified id.
function clicked(inp){
const newArray = [];
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const inputIndex = newArray.findIndex((item) => item.id === inp);
if (inputIndex > -1) {
newArray[inputIndex].stock = newArray[inputIndex].stock + 1;
} else {
mainArray.forEach((element) => {
if(inp == element.id){
newArray.push(element);
}
});
}
console.log(newArray);
}
you can find inp in 2 arrays, then update or create new element for newArray
const newArray = [];
const mainArray = [{
id: 1,
name: "Shoes",
stock: 5,
price: 10
},
{
id: 2,
name: "Bag",
stock: 10,
price: 50
},
];
function clicked(inp) {
let exist = newArray.find(ele => ele.id === inp)
if(exist) {
exist.stock++
} else {
let {id,name, price} = mainArray.find(ele => ele.id === inp)
exist = {id,name, price, stock: 1};
newArray.push({...exist})
}
console.log('newArray :', newArray)
console.log('mainArray :', mainArray)
}
<button id="1" onClick="clicked(2)">Click me</button>

Get value from child Array with a given ID

I have the following Array and I'm trying to print the child array value using .find by providing an ID
connections = [
{
group: 'a',
items: [
{
id: '1',
name: 'Andre'
},
{
id: '2',
name: 'David'
}
]
},
{
group: 'b',
items: [
{
id: '3',
name: 'Brandon'
}
]
},
]
I have tried the following in my Angular app,
getUser(id) {
this.activeItem = this.connections.items.find(data => data.id === id);
console.log(this.activeItem);
}
I'm providing the correct ID but I'm getting an error saying,
error TS2339: Property 'items' does not exist on type....
Thank you.
You can use filter and some methods. This approach will filter array and your array will contain only desired items:
let connections = [
{
group: 'a',
items: [
{
id: '1', name: 'Andre'
},
{
id: '2', name: 'David'
}
]
},
{
group: 'b',
items: [
{
id: '3', name: 'Brandon'
}
]
},
]
let id = 3;
// ONE WAY
const result = connections.filter(f=> f.items.some(s=> s.id == id))
.flatMap(fm => fm.items);
console.log(`result: `, result);
// OR ANOTHER WAY:
const resultWithGroup = connections.filter(f=> f.items.some(s=> s.id == id));
const resultItem = Object.assign({}, ...resultWithGroup).items.find(f => f.id == id);
console.log(`resultItem: `, resultItem);
console.log(`resultItem as an array: `, [resultItem]);
In addition, it is possible to use flatMap method. By using this approach you are getting all items with desired id and then find the first element with id == 3:
let connections = [
{
group: 'a',
items: [
{
id: '1', name: 'Andre'
},
{
id: '2', name: 'David'
}
]
},
{
group: 'b',
items: [
{
id: '3', name: 'Brandon'
}
]
},
]
const result = connections.flatMap(f => f.items).find(f => f.id == id);
console.log(`result as array`, [result]);
You can use flatMap
Try like this:
getUser(id) {
this.activeItem = this.connections.flatMap(x => x.items).find(data => data.id === id);
console.log(this.activeItem);
}
Working Demo
As i can see from the Json object, the items arrays are grouped inside their parent objects. So first you would have to flatten the grouped array:
let items = []
connections.forEach(obj => obj.items.forEach( item => items.push(item)))
Now the items array would only be item objects so it will be easier to do a find:
items.find(item => item.id == 3)
You are trying to use an array without specifying the element of the array
-----------------\/ here
this.connections[0].items.find(data => data.id === id);
The reason your "this.connections.items.find" is not working is that connections variable here represents an array of objects, you cannot directly access a key that is inside an objects contained in an array of objects.
Use this code instead:
this.activeItem = this.connections.filter(obj => obj.items.find(val => val.id == id));
console.log(this.activeItem.items);
connections variable is an array and you are trying to access it as an object. PFB the below code it should be working fine for you.
getUser(id) {
this.activeItem = connections.find(function(element) { return element.items.find(function(el){return el.id==id;}); });
console.log(this.activeItem);
}
Try this. (You made mistake with connections.items)
getUser(id) {
let activeItemIndex = -1;
this.connections.forEach((c) => {
activeItemIndex = c.items.findIndex(item => item.id === id);
if (activeItemIndex > -1) {
this.activeItem = c.items[activeItemIndex];
}
});
}
It is normal that you get this error: "error TS2339: Property 'items' does not exist on type....".
Actually, 'connections' is an array and does not have any prperty 'items'.
'items' is an attribut of the elements contained in 'connections' array.
You can try something like:
getUser(id) {
for (const element of this.connections) {
this.activeItem = element.items.find(data => data.id === id);
if (this.activeItem) {
break;
}
}
console.log(this.activeItem);
}
Once 'this.activeItem' is found we exit the loop with the 'break;' statement.
You have to specify index of connections.
But this is the better solution, Because you have all the users in one place:
getUser(id) {
users = connections.reduce((users, item)=>{
users.push(...item.items);
return users;
}, []);
this.activeItem = users.find(data => data.id === id);
console.log(this.activeItem);
}

How to access an array of objects which is a key-value pair

i want to access the id 'qwsa221' without using array index but am only able to reach and output all of the array elements not a specific element.
i have tried using filter but couldnt figure out how to use it properly.
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
Use Object.keys() to get all the keys of the object and check the values in the array elements using . notation
let lists = {
def453ed: [{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
Object.keys(lists).forEach(function(e) {
lists[e].forEach(function(x) {
if (x.id == 'qwsa221')
console.log(x)
})
})
You can use Object.Keys method to iterate through all of the keys present.
You can also use filter, if there are multiple existence of id qwsa221
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
let l = Object.keys(lists)
.map(d => lists[d]
.find(el => el.id === "qwsa221"))
console.log(l)
you can do it like this, using find
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
console.log(
lists.def453ed // first get the array
.find( // find return the first entry where the callback returns true
el => el.id === "qwsa221"
)
)
here's a corrected version of your filter :
let lists = {def453ed: [{id: "qwsa221",name: "Mind"},{id: "jwkh245",name: "Space"}]};
// what you've done
const badResult = lists.def453ed.filter(id => id === "qwsa221");
/*
here id is the whole object
{
id: "qwsa221",
name: "Mind"
}
*/
console.log(badResult)
// the correct way
const goodResult = lists.def453ed.filter(el => el.id === "qwsa221");
console.log(goodResult)
// filter returns an array so you need to actually get the first entry
console.log(goodResult[0])

How to filter array of objects and get filtered object value

I have an array model as below:
nodes:[
{ id: 1, label: 'label1'},
{ id: 2, label: 'label2'},
{ id: 3, label: 'label3'}
]
I whant to get the label of node filtering by id
I tried the next way, but dont get it work
const selectedNode = 2;
const nodeLabel = nodes.filter(({id}) => id.label ? id === selectedNode) // its filter here
You can use find method by passing a callback provided function.
The find() method returns the value of the first element in the array that passed the provided testing function. Otherwise undefined is returned.
let nodes=[
{ id: 1, label: 'label1'},
{ id: 2, label: 'label2'},
{ id: 3, label: 'label3'}
];
let id=2;
let node = nodes.find(a=>a.id == id);
console.log(node ? node.label : 'id not found');
nodes.find(node => node.id === selectedNode).label
You were quite close.
This line
nodes.filer(({id}) => id.label ? id === selectedNode)
has few issues (assuming filer was just a typo)
It is comparing an integer with an object. (id is the object here)
filter will give you the list of objects rather than its property label.
You were comparing label with id value.
{id} to be replaced by id.
Just modify this to
nodes.filter( (id) => id.id === selectedNode )[0].label
Demo
var nodes = [
{ id: 1, label: 'label1'},
{ id: 2, label: 'label2'},
{ id: 3, label: 'label3'}
];
var selectedNode = 2;
console.log( nodes.filter( (id) => id.id === selectedNode )[0].label );
There's a few ways you could do what you're trying to do. Here are a couple using native Array methods.
Chain filter and map and destructure the returned array.
const [nodeLabel] = nodes
.filter(({id}) => id === selectedNode)
.map(({label}) => label)
Use reduce
const nodeLabel = nodes
.reduce((returnValue, item) => {
if (item.id === selectedNode) return item.label
return returnValue
})

Remove object from array knowing its id [duplicate]

This question already has answers here:
How can I remove a specific item from an array in JavaScript?
(142 answers)
Closed 7 years ago.
I have an array of objects:
var myArr;
Let’s say that on page load it contains 10 objects with the following structure:
{
Id: …,
Name: …
}
How can I remove an object from myArr by its Id?
Try like this
var id = 2;
var list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
var index = list.map(x => {
return x.Id;
}).indexOf(id);
list.splice(index, 1);
console.log(list);
JSFIDDLE
Or you can utilize .filter()
Like this
var id = 2;
var list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
var lists = list.filter(x => {
return x.Id != id;
})
console.log(lists);
DEMO
Two solutions, one evolve creating new instance and one changes the instance of your array.
Filter:
idToRemove = DESIRED_ID;
myArr = myArr.filter(function(item) {
return item.Id != idToRemove;
});
As you can see, the filter method returns new instance of the filtered array.
Second option is to find the index of the item and then remove it with splice:
idToRemove = DESIRED_ID;
index = myArr.map(function(item) {
return item.Id
}).indexOf(idToRemove);
myArr.splice(index, 1);
can you try
newArray = myArr
.filter(function(element) {
return element.id !== thisId;
});

Categories