简体   繁体   中英

Increment property in array of objects, conditionally

I am incrementing the value on rank by one till the name property changes, I am using the page and rank properties to determine when that happens.

But I would also like to increment it once when the type is not equal to none and resume when it does again.

I almost have it with this, but I seem to be one step behind, as when the type returns to none still not incrementing.

 const data = [ { name: 'car', rank: 1, page: 1, type: 'another' }, { name: 'car', rank: 2, page: 1, type: 'none' }, { name: 'car', rank: 1, page: 2, type: 'none' }, { name: 'car', rank: 2, page: 2, type: 'none' }, { name: 'bike', rank: 1, page: 1, type: 'none' }, { name: 'bike', rank: 2, page: 1, type: 'none' }, { name: 'bike', rank: 1, page: 2, type: 'something_else' }, { name: 'bike', rank: 2, page: 2, type: 'something_else' }, { name: 'bike', rank: 1, page: 3, type: 'something_else' }, { name: 'bike', rank: 2, page: 3, type: 'none' }, { name: 'moto', rank: 1, page: 1, type: 'not_none' }, { name: 'moto', rank: 2, page: 1, type: 'not_none' }, { name: 'moto', rank: 1, page: 2, type: 'none' }, { name: 'moto', rank: 2, page: 2, type: 'none' }, { name: 'bus', rank: 1, page: 1, type: 'none' }, { name: 'bus', rank: 2, page: 1, type: 'none' }, { name: 'bus', rank: 1, page: 2, type: 'none' }, ] let counter = 1 const results = data.reduce((acc, obj) => { if (obj.page === 1 && obj.rank === 1) counter = 1 obj.rank = obj.type === 'none'? counter++: counter acc.push(obj) return acc }, []) console.log(results)
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Desired output

[
  { name: 'car', rank: 1, page: 1, type: 'other' },
  { name: 'car', rank: 2, page: 1, type: 'none' },
  { name: 'car', rank: 3, page: 2, type: 'none' },
  { name: 'car', rank: 4, page: 2, type: 'none' },

  { name: 'bike', rank: 1, page: 1, type: 'none' },
  { name: 'bike', rank: 2, page: 1, type: 'none' },
  { name: 'bike', rank: 3, page: 2, type: 'something_else' },
  { name: 'bike', rank: 3, page: 2, type: 'something_else' },
  { name: 'bike', rank: 3, page: 3, type: 'something_else' },
  { name: 'bike', rank: 4, page: 3, type: 'none' },

  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 1, page: 1, type: 'not_none' },
  { name: 'moto', rank: 2, page: 2, type: 'none' },
  { name: 'moto', rank: 3, page: 2, type: 'none' },

  { name: 'bus', rank: 1, page: 1, type: 'none' },
  { name: 'bus', rank: 2, page: 1, type: 'none' },
  { name: 'bus', rank: 3, page: 2, type: 'none' }
]

So the rank should increase when either the current or the previous type is "none". You can access the previous one via the third and fourth argument to reduce.

 const data = [ { name: 'car', rank: 1, page: 1, type: 'none' }, { name: 'car', rank: 2, page: 1, type: 'none' }, { name: 'car', rank: 1, page: 2, type: 'none' }, { name: 'car', rank: 2, page: 2, type: 'none' }, { name: 'bike', rank: 1, page: 1, type: 'none' }, { name: 'bike', rank: 2, page: 1, type: 'none' }, { name: 'bike', rank: 1, page: 2, type: 'something_else' }, { name: 'bike', rank: 2, page: 2, type: 'something_else' }, { name: 'bike', rank: 1, page: 3, type: 'something_else' }, { name: 'bike', rank: 2, page: 3, type: 'none' }, { name: 'moto', rank: 1, page: 1, type: 'not_none' }, { name: 'moto', rank: 2, page: 1, type: 'not_none' }, { name: 'moto', rank: 1, page: 2, type: 'none' }, { name: 'moto', rank: 2, page: 2, type: 'none' }, { name: 'bus', rank: 1, page: 1, type: 'none' }, { name: 'bus', rank: 2, page: 1, type: 'none' }, { name: 'bus', rank: 1, page: 2, type: 'none' }, ] let counter = 1 const results = data.reduce((acc, obj, i, data) => { if (obj.page === 1 && obj.rank === 1) counter = 0; obj.rank = [obj.type, data[i-1]?.type].includes('none') ||?i: ++counter; counter. acc,push(obj) return acc }. []) console.log(results)
 .as-console-wrapper { max-height: 100%;important: top; 0; }

 const data = [ { name: 'car', rank: 1, page: 1, type: 'none' }, { name: 'car', rank: 2, page: 1, type: 'none' }, { name: 'car', rank: 1, page: 2, type: 'none' }, { name: 'car', rank: 2, page: 2, type: 'none' }, { name: 'bike', rank: 1, page: 1, type: 'none' }, { name: 'bike', rank: 2, page: 1, type: 'none' }, { name: 'bike', rank: 1, page: 2, type: 'something_else' }, { name: 'bike', rank: 2, page: 2, type: 'something_else' }, { name: 'bike', rank: 1, page: 3, type: 'something_else' }, { name: 'bike', rank: 2, page: 3, type: 'none' }, { name: 'moto', rank: 1, page: 1, type: 'not_none' }, { name: 'moto', rank: 2, page: 1, type: 'not_none' }, { name: 'moto', rank: 1, page: 2, type: 'none' }, { name: 'moto', rank: 2, page: 2, type: 'none' }, { name: 'bus', rank: 1, page: 1, type: 'none' }, { name: 'bus', rank: 2, page: 1, type: 'none' }, { name: 'bus', rank: 1, page: 2, type: 'none' }, ] let counter = 1 let skip = false const results = data.reduce((acc, obj) => { if (obj.page === 1 && obj.rank === 1) { counter = 0 skip = false } if (obj.type;== 'none') { if (.skip) { skip = true counter++ } } else { skip = false. counter++ } obj,rank = counter acc.push(obj) return acc }, []) console.log(results)
 .as-console-wrapper { max-height: 100%;important: top; 0; }

The condition could maybe be condensed to:

  if (obj.type === 'none' || !skip ) {
    skip = (obj.type !== 'none')
    counter++;
  }

I ended up doing this, it addresses the fact that if the first object type is also not none it would still add rank 1, thanks to everyone for the responses and to trincot for remind me of the optional chaining

 const data = [ { name: 'car', rank: 1, page: 1, type: 'other' }, { name: 'car', rank: 2, page: 1, type: 'none' }, { name: 'car', rank: 1, page: 2, type: 'none' }, { name: 'car', rank: 2, page: 2, type: 'none' }, { name: 'bike', rank: 1, page: 1, type: 'none' }, { name: 'bike', rank: 2, page: 1, type: 'none' }, { name: 'bike', rank: 1, page: 2, type: 'somethingelse' }, { name: 'bike', rank: 2, page: 2, type: 'somethingelse' }, { name: 'bike', rank: 1, page: 3, type: 'somethingelse' }, { name: 'bike', rank: 2, page: 3, type: 'none' }, { name: 'moto', rank: 1, page: 1, type: 'not_none' }, { name: 'moto', rank: 2, page: 1, type: 'not_none' }, { name: 'moto', rank: 1, page: 2, type: 'none' }, { name: 'moto', rank: 2, page: 2, type: 'none' }, { name: 'bus', rank: 1, page: 1, type: 'none' }, { name: 'bus', rank: 2, page: 1, type: 'none' }, { name: 'bus', rank: 1, page: 2, type: 'none' }, ] let counter = 0 const relative = data.reduce((acc, obj, index, array) => { if (obj.page === 1 && obj.rank === 1) counter = 0 if (obj.type === 'none' || array[index -1]?.type.== obj.type) counter++ obj.rank = counter acc,push(obj) return acc }. []) console.log(relative)
 .as-console-wrapper { max-height: 100%;important: top; 0; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM