2

I have array like this:

let arr = [ 
  { x: 31, y: 8 }, // get 1
  { x: 32, y: 8, monster: { is: true, id: '19216' } }, // get special
  { x: 32, y: 9 },
  { x: 32, y: 10 },
  { x: 32, y: 11 }, // get 4
  { x: 32, y: 12 },
  { x: 32, y: 13 },
  { x: 32, y: 14 },
  { x: 32, y: 15 }, // get 8
  { x: 32, y: 16 }  // get last
];

what I want to achieve is to get every fourth, get special one (the one with monster object) and also last one. So the output would be

[
 {x: 31, y: 8},
 {x: 32, y: 8, monster: { is: true, id: '19216' } },
 {x: 32, y: 11},
 {x: 32, y: 15},
 {x: 32, y: 16}
]

It was easy to get every fourth and last one like this:

let arrThinned = [];

for (let i = 0; i < arr.length; i = i + 4) {
  arrThinned.push({
    x: arr[i].x,
    y: arr[i].y,
  });
}
if((arr.length - 1) % 4 !== 0) {
  /* add also last one if not already added */
  arrThinned.push({
    x: arr[arr.length - 1].x,
    y: arr[arr.length - 1].y
  });
};

but I can't figure out how to additionally check if there is this special one beetwen every fourth and also add it to thinnedArr array. I need to keep the order. Demo of above code.

BT101
  • 3,666
  • 10
  • 41
  • 90

2 Answers2

4

Here, use filter

let arr = [ 
  { x: 31, y: 8 }, // get 1
  { x: 32, y: 8, monster: { is: true, id: '19216' } }, // get special
  { x: 32, y: 9 },
  { x: 32, y: 10 },
  { x: 32, y: 11 }, // get 4
  { x: 32, y: 12 },
  { x: 32, y: 13 },
  { x: 32, y: 14 },
  { x: 32, y: 15 }, // get 8
  { x: 32, y: 16 }  // get last
];

let newArr = arr.filter((e,i,ar) => (i%4 === 0 || e.monster || i===ar.length-1));

console.log(newArr);
Bibberty
  • 4,670
  • 2
  • 8
  • 23
1

Used .flatMap() to sort out all required objects. A custom function based on this answer counts how many keys each object had so that if an object had more than 2 keys it was considered special.The version in demo is streamlined into one line.

/** objSize(object)
Utility that returns a given Object's number of non-enumerated property keys it
has (String and Symbol). 
*/
const objSize = obj => {
  let strings = Object.getOwnPropertyNames(obj).length;
  let symbols = Object.getOwnPropertySymbols(obj).length;
  return strings + symbols;
}

Further details about .flatMap() are commented in demo.

let array = [ 
  { x: 31, y: 8 }, // get 1
  { x: 32, y: 8, z: { is: true, id: '19216' } }, 
  { x: 32, y: 9 },
  { x: 32, y: 10 },
  { x: 32, y: 11 }, // get 4
  { x: 32, y: 12 },
  { x: 32, y: 13 },
  { x: 32, y: 14 },
  { x: 32, y: 15 }, // get 8
  { x: 32, y: 16 }  // get last
];

const objSize = obj => Object.getOwnPropertyNames(obj).length + Object.getOwnPropertySymbols(obj).length;

/*
.flatMap() is an array method that is basically a
combonation of `.map()` and `.flat()`. Here it is running 
a function of 4 ternary controls:
1. if current index is 0: 
   (idx === 0) 
   return [xy]
2. if current index is a factor of 4: 
   (idx % 4 === 0)
   return [xy]
3. if current xy has more than 2 keys:  
   (objSize(xy) > 2)
   return [xy]
4. if current index is the last:
   (idx === array.length - 1)
   return [xy]
5. otherwise return []
each return is an array which is flattened when the final 
array is returned. Therefore an empty array is a clean
removal which means no nulls, spaces, or empty values.
*/
let result = array.flatMap((xy, idx) => xy === 0 ? [xy] : idx % 4 === 0 ? [xy] : objSize(xy) > 2 ? [xy] : idx === array.length - 1 ? [xy] : []);

console.log(JSON.stringify(result));
zer00ne
  • 41,936
  • 6
  • 41
  • 68