0

I'm pretty new to AppScript and I have absolutely no idea how to manipulate arrays. I just want to be able to take one array and collapse the common elements in a separate array as follows;

groceryArray = [
                ["fruit", "apple"],
                ["fruit", "banana"], 
                ["veg", "potato"], 
                ["veg", "onion"], 
                ["veg", "broccoli"],
               ]

and turn that into this...

groceryArray2 = [
                  ["fruit", ["apple", "banana"]], 
                  ["veg", ["potato", "onion", "broccoli"]],
                 ]

I would of thought it's fairly straightforward but I can't work it out at all...

3
  • 1
    How about doing converting it to `{"fruit",["apple","banana"],"veg":["potato","onion","brocolli"]} Commented Oct 15, 2020 at 19:32
  • Yeah, that could work. Is it easier to convert it into a dictionary? Commented Oct 15, 2020 at 19:36
  • @JonPhillips - it's not easier, it is more performant (albeit on such an array size it is pretty much irrelevant). Other than that, not much of a difference, it all depends on how you are going to use it. Commented Oct 16, 2020 at 3:14

2 Answers 2

2

Create a Map and reduce the array:

/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
const groceryArray = [
            ["fruit", "apple"],
            ["fruit", "banana"], 
            ["veg", "potato"], 
            ["veg", "onion"], 
            ["veg", "broccoli"],
           ],
  collapsedMap = groceryArray.reduce((m,[category,item]) => m.set(category, m.has(category) ? m.get(category).concat(item):[item]),new Map),
  collapsedArray = [...collapsedMap];
console.info({collapsedMap,collapsedArray});
<!-- https://meta.stackoverflow.com/a/375985/ -->    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

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

Comments

2

What you actually want to achieve is fold a grid over the first column of each row. In a nutshell, this is a very simple algorithmic problem:

  1. Iterate over grid rows, for each row check if the property exists and is an array:

    1. If yes, push the new item into the array.
    2. If no, set the property to be an array with one current item.

TheMaster's answer demonstrates one approach, below is an alternative one (they both follow the same algorithm) using for...of, simple dictionary, and Object.entries:

const groceryArray = [
  ["fruit", "apple"],
  ["fruit", "banana"],
  ["veg", "potato"],
  ["veg", "onion"],
  ["veg", "broccoli"],
];

const fold = (grid, col = 0) => {

  const folded = {};

  for(const [ cat, item ] of grid) {
    const existing = folded[cat];
    
    if(existing) {
      existing.push(item);
      continue;
    }
    
    folded[cat] = [ item ];
  }
  
  return Object.entries(folded);
};

console.log( fold(groceryArray) );

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.