4

I have an array of nested arrays containing coordinates. I would like to create a new array containing nested arrays of coordinates based on if they have the same latitude. The description might be a little confusing, so here some examples and code

Initial array (latitude is the second value of the number pairs)

const coordinateArray = [[46,11], [38,11], [44,9], [81,15], [55,15]];

Expected outcome:

const newArray = [
                  [[46,11],[38,11]],
                  [[81,15],[55,15]], 
                  [[44,9]]
                 ];

I tried this, but it returns every coordinate in a new array instead of pairing the ones with same latitude:

const rowArrays = [];
coordinateArray.map(c => {
    const row = [c];
    for (let i = 0; i < coordinateArray.length; i++) {
      console.log(c[1], coordinateArray[i][1]);
      if (c[1] === [1]) {
        row.push(coordinateArray[i]);
        coordinateArray.splice(0, 1);
      }
    }
    return rowArrays.push(row);
  });

Would be grateful for any suggestions

3 Answers 3

4

Your solution is close, but as you mentioned, it unconditionally creates a new array with each iteration through coordinateArray. Because your input-to-output is not 1:1 and instead you're looking to change the shape, reduce would be preferable to map.

If you reduced the array into an object based on the latitude, you could then use Object.values to achieve the result in your desired shape.

const coordinateArray = [[46,11], [38,11], [44,9], [81,15], [55,15]];
const matched = coordinateArray.reduce((out,arr) => {
  out[arr[1]] = out[arr[1]] //Have we already seen this latitude?
    ? [arr, ...out[arr[1]]] //Yes: Add the current coordinates to that array
    : [arr];                //No: Start a new array with current coordinates
  return out;
  }, {});

//const matched looks like this:
//{
//  "9":  [[44,9]],
//  "11": [[38,11],[46,11]],
//  "15": [[55,15],[81,15]]
//}
  
console.log(Object.values(matched)); //We only care about the values

If you favor brevity and/or have a bone to pick with your fellow developers, the reduce could be converted to a single expression using spread operators (...) and a falsy coalesce (out[arr[1]] || []).

const coordinateArray = [[46,11], [38,11], [44,9], [81,15], [55,15]];
const matched = coordinateArray.reduce((out,arr) => ({...out, [arr[1]]: [arr, ...(out[arr[1]] || [])]}), {});
console.log(Object.values(matched));

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

1 Comment

Thanks a lot! This is what I needed
0

Create a map and group:

const coordinateArray = [[46,11], [38,11], [44,9], [81,15], [55,15]];
let map = coordinateArray.reduce((map,coord)=>{
  map.has(coord[1]) ? map.get(coord[1]).push(coord) : map.set(coord[1], [coord]);
  return map;
},new Map())
console.info([...map.values()])

Comments

0

There are definitely better ways to write this with less lines of code posted above, but this might be a little bit easier for you to follow:

const coordinateArray = [[46,11], [38,11], [44,9], [81,15], [55,15]];

const rowArrays = [];

coordinateArray.forEach(c => {
    // set match to false at the beginning of every new coordinate
    let match = false;
    rowArrays.forEach (r => {
      // check if your coordinate lattitude already exists in rowArrays
      // if it does, push it to that array, and set match to true
      if (r[0][1] === c[1]) {
        r.push(c);
        match = true;
      }
    });
    // after iterating through every item in rowArrays, if you still
    // haven't found a match, push the new array to rowArrays.
   if(!match){
    rowArrays.push([c])
   }
  });

console.log(rowArrays)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.