最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript - Add Item in the middle of an array inside map function - Stack Overflow

programmeradmin8浏览0评论

I'm trying to add an item in a specific index inside an array inside a map function and it's been behaving unexpectedly. Here's the code for it

const addItemToLevelTwoArray= (uniqueID, arrayID )=> {
  const reportObject = {
    id:arrayID,
    title:'',
  }
  
  data.map(section=>{
    section.content.map((report, reportIndex)=>{
      if(report.id===uniqueID){
        section.content.splice(reportIndex, 0, reportObject);
      }
      return report;
    })
   return section;
  })
}

Here's a working pen -

Expected behaviour is that it would insert an object in the specific index, right above the object where the ID matches.

However, it's acting weirdly and sometimes I'm getting 2 items being added instead of one.

Any tip on what I'm doing would be massively appreciated! I know I'm close but I've been stuck on this for a while now and can't figure out what I'm doing wrong!

I'm trying to add an item in a specific index inside an array inside a map function and it's been behaving unexpectedly. Here's the code for it

const addItemToLevelTwoArray= (uniqueID, arrayID )=> {
  const reportObject = {
    id:arrayID,
    title:'',
  }
  
  data.map(section=>{
    section.content.map((report, reportIndex)=>{
      if(report.id===uniqueID){
        section.content.splice(reportIndex, 0, reportObject);
      }
      return report;
    })
   return section;
  })
}

Here's a working pen - https://codepen.io/raufabr/pen/vYZYgOV?editors=0011

Expected behaviour is that it would insert an object in the specific index, right above the object where the ID matches.

However, it's acting weirdly and sometimes I'm getting 2 items being added instead of one.

Any tip on what I'm doing would be massively appreciated! I know I'm close but I've been stuck on this for a while now and can't figure out what I'm doing wrong!

Share Improve this question asked Aug 23, 2021 at 17:29 theabrartheabrar 4501 gold badge8 silver badges18 bronze badges 1
  • 1 You're using map incorrectly. If you're not using the array that map builds and returns, there's no reason to use it; just use a loop or forEach. More in my post here. And the great thing about using a loop is you can just...add another entry, since you're the one building the result. – T.J. Crowder Commented Aug 23, 2021 at 17:32
Add a ment  | 

3 Answers 3

Reset to default 3

Preface: You're using map incorrectly. If you're not using the array that map builds and returns, there's no reason to use it; just use a loop or forEach. More in my post here. And one reason to use an old-fashioned for loop is that you're in control of iteration, which matters because...

However, it's acting weirdly and sometimes I'm getting 2 items being added instead of one.

That's because you're inserting into the array being looped by the map, so on the next pass, it picks up the entry you're adding.

If you do a simple loop, you can easily avoid that by incrementing the index when you insert, or by looping backward; here's the looping backward approach:

const addItemToLevelTwoArray = (uniqueID, arrayID) => {
    const reportObject = {
        id: arrayID,
        title: "",
    };
  
    for (const section of data) {
        for (let reportIndex = section.content.length - 1; reportIndex >= 0; --reportIndex) {
            const report = section.content[reportIndex];
            if (report.id === uniqueID) {
                 section.content.splice(reportIndex, 0, reportObject);
            }
        }
    }
};

Because we're looping backward, we won't pick up the entry we just added on the next pass.

Since the outer loop doesn't have that problem, I used the more convenient for-of.


Since you asked about map, if you do use the array map returns, you can do this by returning an array with the two entries, and then calling flat on the array map builds. (This only works if the array doesn't already contain arrays, because they'll get flattened to.) This is mon enough that it's bined in one function: flatMap. It's not what I'd do (I'd do a loop), but it's certainly feasible. Sticking with forEach and flatMap rather than using for-of and for:

const addItemToLevelTwoArray = (uniqueID, arrayID) => {
    const reportObject = {
        id: arrayID,
        title: "",
    }
  
    data.forEach(section => {
        section.content = section.content.flatMap(report => {
            if (report.id === uniqueID) {
                // Return the new one and the old one
                return [reportObject, report];
            }
            // Return just the old one
            return report;
        });
    });
};

That assumes it's okay to modify the section object. If it isn't, Alberto Sinigaglia's answer shows creating a new replacement object instead, which is handy in some sitautions.

You can just use flatMap:

const data = [
  {
    content: [
      {
        id: 1,
        title: "a"
      },{
        id: 3,
        title: "c"
      },
    ]
  }
]

const addItemToLevelTwoArray= (uniqueID, arrayID )=> {
  const reportObject = {
    id:arrayID,
    title:'',
  }
  
  return data.map(section=> {
      return {
        ...section,
        content: section.content.flatMap( report =>
          report.id === uniqueID 
             ? [reportObject, report]
             : report
          )
      }
    }
  )
}
console.log(addItemToLevelTwoArray(3, 2))

The following will extend the inner array .contentwithout modifying the original array data:

const data = [ {id: 0,title:'main',content:[{id:1,title:'Hello'}, 
                                            {id:2,title:"World"}] } ];

const addItemToLevelTwoArray= (uniqueID, arrayID )=> {
  const reportObject = {
    id:arrayID,
    title:'something new!',
  }
  return data.map(d=>(
    {...d, content:d.content.reduce((acc, rep)=>{
      if(rep.id===uniqueID) acc.push(reportObject);
      acc.push(rep)
      return acc;
    },[]) // end of .reduce() 
  })); // end of .map()
}

const res=addItemToLevelTwoArray(1,123);
console.log(res);

发布评论

评论列表(0)

  1. 暂无评论