1

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?

5
  • You're returning the same object in both if and else. Commented Jun 29, 2018 at 20:33
  • Is date supposed to be a string? It needs quotes around it. Commented Jun 29, 2018 at 20:35
  • ok i update with real statement Commented Jun 29, 2018 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. Commented Jun 29, 2018 at 20:37
  • Bermar any ideas? Commented Jun 29, 2018 at 20:44

5 Answers 5

1

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.

 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);

Sign up to request clarification or add additional context in comments.

2 Comments

Would incorrectly insert if the new item is the last item, try it with a date in 2019
@HMR Good catch, added a check for that.
0

.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:

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)

1 Comment

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
0

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));

Comments

0

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.

See how insertWhen is a high order function which takes two different functions cond and comparer:

  • cond is a function that should return true or false when evaluating each given array item to find where to insert the new item.
  • compare is a function that should return -1 if you want to add the item before the found one, or 1 if you want to add the item after the found one. This function may use moment to return -1 or 1 depending on your needs.

Inserts the new item after the matched one

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)


Inserts the new item before the matched one

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)

3 Comments

Item will never be inserted if it's the last, try it with a new item that has a date in 2019
@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.
@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.
0
arr.slice(0,idx).concat([element_to_insert].concat(arr.slice(idx+1,arr.length).map(n=>{
    n.asc_id++;
    return n;
})))

3 Comments

How does this increment the asc_id in the elements after the one that's inserted?
@Barmar valid, I modified it a bit
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.