nick
nick

Reputation: 1178

Cannot read properties of undefined (reading 'size')

I have 2 arrays. I'm using a for loop on arr1 and checking if arr2 contains some of the same shoe sizes as in arr1. If the condition checks that a shoe size from arr1 does not exist in arr2, then it will push an object ({size: '-'}) to the newArr, if it does exist it will just push the shoe object from arr2 into newArr

code:

const newArr = []
    const arr1 = [
        { size: 'US 3' },
        { size: 'US 4' },
        { size: 'US 5' },
        { size: 'US 6' },
        { size: 'US 7' },
        { size: 'US 8' },
        { size: 'US 9' },
        { size: 'US 10' },
        { size: 'US 11' },
        { size: 'US 12' },
        { size: 'US 13' },
        { size: 'US 14' },
        { size: 'US 15' },
        { size: 'US 16' }
    ]
    const arr2 = [
        { size: '4', cost: '170' },
        { size: '6', cost: '75' },
        { size: '7', cost: '75' },
        { size: '8', cost: '78' },
        { size: '9', cost: '80' },
        { size: '10', cost: '85' },
        { size: '11', cost: '73' },
        { size: '12', cost: '77' },
        { size: '14', cost: '100' }
    ]

     for (const arr1Item in arr1) {
         let arr1Size = arr1[arr1Item].size
         let includes = arr1Size.includes(arr2[arr1Item].size);
    
         if(includes) {
           newArr.push(arr2[arr1Item])
         } else {
           newArr.push({size: '-'})
         }
      }
 
 console.log(newArr)

The problem is whenever I run this I get this error: TypeError: Cannot read properties of undefined (reading 'size')

This error is happening because of this code here:

arr2[arr1Item].size

The thing I'm confused about is if I console.log(arr2[arr1Item]) INSIDE the for loop, it returns each object from arr2 with no error, only gives an error when I add .size.

I've been stuck on this for a bit, would appreciate any help. Thank you.

Upvotes: 0

Views: 11934

Answers (2)

Biotox
Biotox

Reputation: 1601

I think you want to use filter for matches.

let newArr = []
const arr1 = [
  { size: 'US 3' },
  { size: 'US 4' },
  { size: 'US 5' },
  { size: 'US 6' },
  { size: 'US 7' },
  { size: 'US 8' },
  { size: 'US 9' },
  { size: 'US 10' },
  { size: 'US 11' },
  { size: 'US 12' },
  { size: 'US 13' },
  { size: 'US 14' },
  { size: 'US 15' },
  { size: 'US 16' }
]
const arr2 = [
  { size: 'US 4', cost: '170' },
  { size: '6', cost: '75' },
  { size: '7', cost: '75' },
  { size: '8', cost: '78' },
  { size: '9', cost: '80' },
  { size: '10', cost: '85' },
  { size: '11', cost: '73' },
  { size: '12', cost: '77' },
  { size: '14', cost: '100' }
]
  
arr1.forEach(a1Item => {
  let foundItems = arr2.filter(a2Item => a2Item.size === a1Item.size);
  // OR PARTIAL MATCH (arr1.size '4' would match arr2.size 'US 4')
  // let foundItems = arr2.filter(a2Item => a2Item.size.includes(a1Item.size));

  if (foundItems.length > 0) {
    foundItems.forEach(fItem => {
      newArr.push(fItem);
    });
  } else {
    // ADDED COST TO KEEP ITEMS CONSISTENT
    newArr.push({size: '-', cost: '-'});
  }
});

console.log(newArr);

Upvotes: 1

user9706
user9706

Reputation:

You iterate over arr1 using the index variable arr1Item, but then use that to index into arr2. As arr1 has more elements than arr2, you end up trying to accessarr2[9] === undefined and undefined does not have a size attribute hence the error TypeError: Cannot read properties of undefined (reading 'size').

Couple of other problems

  1. newArr is not a const.

  2. Array.protoype.includes() is used to see if, say, 4 of arr2.size matches arr.size like US 4 but this will also incorrectly (substring) match US 14.

Potential solution

Using the fact that both arr1 & arr2 are sorted by the (normalized) size attribute, and that the set of (normalized) arr2.size is a subset of (normalized) arr1.size you can do the transformation in linear time (O(arr1.length)):

const arr1 = [
    { size: 'US 3' },
    { size: 'US 4' },
    { size: 'US 5' },
    { size: 'US 6' },
    { size: 'US 7' },
    { size: 'US 8' },
    { size: 'US 9' },
    { size: 'US 10' },
    { size: 'US 11' },
    { size: 'US 12' },
    { size: 'US 13' },
    { size: 'US 14' },
    { size: 'US 15' },
    { size: 'US 16' }
]
const arr2 = [
    { size: '4', cost: '170' },
    { size: '6', cost: '75' },
    { size: '7', cost: '75' },
    { size: '8', cost: '78' },
    { size: '9', cost: '80' },
    { size: '10', cost: '85' },
    { size: '11', cost: '73' },
    { size: '12', cost: '77' },
    { size: '14', cost: '100' }
]

let newArr = []
for(let i1 = 0, i2 = 0; i1 < arr1.length; i1++) {
        if(i2 < arr2.length && arr1[i1].size.substr(3) === arr2[i2].size) {
                newArr.push(arr2[i2]);
                i2++;
        } else {
                newArr.push({size: '-'});
        }
}
console.log(newArr)

Upvotes: 1

Related Questions