javascript insert object to array at specific point id and increment others id
javascript insert object to array at specific point id and increment others id
I have little problem with js arrays. I want to insert object on if statement and increase id on anothers objects
var arr=[{asc_id:1, date:2018-06-29, name:"first"},
{asc_id:2, date:2018-06-30, name:"second"},
{asc_id:3, date:2018-07-10, name:"fourth"},
{asc_id:4, date:2018-07-10, name:"fifth"}];
var checkedItem={asc_id:4, date:2018-06-30, name:"third"};
let savingDate = moment(checkedItem.date)
var newArr = arr.map((item,key)=>{
if(savingDate.isSame(item.date) || savingDate.isAfter(item.date)){
console.log(true)
return{
//code here
}
}else{
return{
//code here
}
console.log(false)
}
})
console.log(newArr)
i want make new array looks like
newArr=[{asc_id:1, date:2018-06-29, name:"first"},
{asc_id:2, date:2018-06-30, name:"second"},
{asc_id:3, date:2018-06-30, name:"third"},
{asc_id:4, date:2018-07-10, name:"fourth"},
{asc_id:5, date:2018-07-10, name:"fifth"}];
map is not good idea? condition i check with momento and check statement is correct only i want how to push object between second and fourth and make asc_id as in code?
if
else
Is
date
supposed to be a string? It needs quotes around it.– Barmar
Jun 29 at 20:35
date
ok i update with real statement
– Piotr Bieszczad
Jun 29 at 20:37
You can't use
.map()
to add to an array, it always returns an array that's the same length as the original. You can use .splice()
to insert into an array.– Barmar
Jun 29 at 20:37
.map()
.splice()
Bermar any ideas?
– Piotr Bieszczad
Jun 29 at 20:44
5 Answers
5
What you can do is make a deep copy of the original array. Then insert the new element in that array at the appropriate place, and then reset all the asc_id
properties.
asc_id
var arr=[{asc_id:1, date:"2018-06-29", name:"first"},
{asc_id:2, date:"2018-06-30", name:"second"},
{asc_id:3, date:"2018-07-10", name:"fourth"},
{asc_id:4, date:"2018-07-10", name:"fifth"}];
var checkedItem={asc_id:4, date:"2018-06-30", name:"third"};
var newArr = arr.map(e => Object.assign({}, e));
var insertPos = newArr.findIndex(({date}) => date > checkedItem.date);
if (insertPos == -1) { // If not found, insert at end
insertPos = newArr.length;
}
newArr.splice(insertPos, 0, checkedItem);
newArr.forEach((e, i) => e.asc_id = i + 1);
console.log(newArr);
Would incorrectly insert if the new item is the last item, try it with a date in 2019
– HMR
Jun 29 at 21:27
@HMR Good catch, added a check for that.
– Barmar
Jun 29 at 21:33
.map
is not a good idea because it returns an array with the same length as the one mapped, you can use a simple for
loop and create an empty array to fill it with values from original array and push the checkedElement
whenever matched , for the asc_id
create a ndx
and increment it:
.map
for
checkedElement
asc_id
ndx
var arr=[{asc_id:1, date:'2018-06-29', name:"first"},
{asc_id:2, date:'2018-06-30', name:"second"},
{asc_id:3, date:'2018-07-10', name:"fourth"},
{asc_id:4, date:'2018-07-10', name:"fifth"}];
var checkedItem={asc_id:4, date:'2018-06-30', name:"third"};
var newArr = , ndx = 0;
arr.forEach((e,i) => {
newArr.push({ ...e, asc_id : ++ndx })
if(e.date === checkedItem.date)
newArr.push({...checkedItem, asc_id : ++ndx })
})
console.log(newArr)
Item is never inserted if it's the last, try with a new item that has a date in 2019. It will also never insert if it's the first, try with date in 2017
– HMR
Jun 29 at 21:26
Other answers re index the entire array, I'm not sure that's what you want, the following uses reduce and will only re index items after the inserted item.
const arr = [
{ asc_id: 5, date: "2018 - 06 - 29", name: "first" },
{ asc_id: 6, date: "2018 - 06 - 30", name: "second" },
{ asc_id: 8, date: "2018 - 07 - 10", name: "fourth" },
{ asc_id: 9, date: "2018 - 07 - 10", name: "fifth" }
];
const checkedItem = { asc_id: "ignored", date: "2018 - 06 - 30", name: "third" };
const addItem = (arr,newItem)=>{
let itemInserted=false;
const newArray = arr.reduce(
(result,item) => {
if(newItem.date.localeCompare(item.date) === -1){
if(!itemInserted){//item has not been inserted yet
result.push({...newItem,asc_id:item.asc_id});
itemInserted=true;
}
result.push({...item,asc_id:item.asc_id+1})
}else{
result.push(item)
}
return result;
},
//initial result
);
if(!itemInserted){//new item was the last item
newArray.push({...newItem,asc_id:arr.slice(-1)[0].asc_id+1});
}
return newArray;
}
console.log(addItem(arr,checkedItem));
Probably you could start implementing a function like the one I provide as part of the following runnable snippet.
Note that the first parameter is a condition: use moment
or whatever to parse a date or operate with any property of any of the existing items.
moment
See how insertWhen
is a high order function which takes two different functions cond
and comparer
:
insertWhen
cond
comparer
cond
compare
-1
1
moment
-1
1
const arr = [{
asc_id: 1,
date: '2018 - 06 - 29',
name: "first"
},
{
asc_id: 2,
date: '2018 - 06 - 30',
name: "second"
},
{
asc_id: 3,
date: '2018 - 07 - 10',
name: "fourth"
},
{
asc_id: 4,
date: '2018 - 07 - 10',
name: "fifth"
}
]
const insertWhen = (cond, comparer, newItem, arr) => {
const foundItem = arr.find(cond)
if (!foundItem) return
let foundItemIndex = arr.indexOf(foundItem)
switch (comparer(foundItem, newItem)) {
case -1:
arr.splice(foundItemIndex + 1, 0, newItem)
arr.slice(foundItemIndex + 1)
.forEach(item => (item.asc_id = ++foundItemIndex + 1))
break
case 1:
arr.splice(foundItemIndex, 0, newItem)
arr.slice(foundItemIndex)
.forEach(item => (item.asc_id = ++foundItemIndex))
break
}
}
var newItem = {
asc_id: 4,
date: '2018-06-30',
name: "third"
}
insertWhen(
({ date }) => date == '2018 - 06 - 30',
(foundItem, newItem) => -1, // INSERT AFTER, wins foundItem
newItem,
arr
)
console.log(arr)
const arr = [{
asc_id: 1,
date: '2018 - 06 - 29',
name: "first"
},
{
asc_id: 2,
date: '2018 - 06 - 30',
name: "second"
},
{
asc_id: 3,
date: '2018 - 07 - 10',
name: "fourth"
},
{
asc_id: 4,
date: '2018 - 07 - 10',
name: "fifth"
}
]
const insertWhen = (cond, comparer, newItem, arr) => {
const foundItem = arr.find(cond)
if (!foundItem) return
let foundItemIndex = arr.indexOf(foundItem)
switch (comparer(foundItem, newItem)) {
case -1:
arr.splice(foundItemIndex + 1, 0, newItem)
arr.slice(foundItemIndex + 1)
.forEach(item => (item.asc_id = ++foundItemIndex + 1))
break
case 1:
arr.splice(foundItemIndex, 0, newItem)
arr.slice(foundItemIndex)
.forEach(item => (item.asc_id = ++foundItemIndex))
break
}
}
var newItem = {
asc_id: 4,
date: '2018-06-30',
name: "third"
}
insertWhen(
({ date }) => date == '2018 - 06 - 30',
(foundItem, newItem) => 1, // INSERT BEFORE, wins the new item
newItem,
arr
)
console.log(arr)
Item will never be inserted if it's the last, try it with a new item that has a date in 2019
– HMR
Jun 29 at 21:23
@HMR Maybe I'm mistaken, but it seems like the OP wants to insert an item between some given date or after one. I don't know if the OP wants to insert the item as the last one if
cond
is never true
.– Matías Fidemraizer
Jun 29 at 22:42
cond
true
@HMR BTW, what has to do the date in 2019? For me, it seems like I should refactor the snippet so it uses a comparer instead of a condition, so the comparer may decide if it goes before or after the found item.
– Matías Fidemraizer
Jun 29 at 22:54
arr.slice(0,idx).concat([element_to_insert].concat(arr.slice(idx+1,arr.length).map(n=>{
n.asc_id++;
return n;
})))
How does this increment the
asc_id
in the elements after the one that's inserted?– Barmar
Jun 29 at 20:39
asc_id
@Barmar valid, I modified it a bit
– JayB
Jun 30 at 3:55
Yuo also need to fix the
asc_id
of the element that you insert, so it's in the proper sequence for the place it gets.– Barmar
2 days ago
asc_id
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You're returning the same object in both
if
andelse
.– Barmar
Jun 29 at 20:33