0

In the example I use a each to go thru select fields and create an array of data, I need to group 2 properties year and cabin also the property months is an array that I would like to merge, thing is I'm having a bit of trouble getting the wanted result:

JSFIDDLE: http://jsfiddle.net/tc39xu6b/2/

Result I get:

[
  {
    "year": "2021",
    "cabin": "1",
    "months": [
      "1",
      "2"
    ]
  },
  {
    "year": "2021",
    "cabin": "1",
    "months": [
      "4"
    ]
  },
  {
    "year": "2021",
    "cabin": "2",
    "months": [
      "1",
      "2"
    ]
  },
  {
    "year": "2022",
    "cabin": "1",
    "months": [
      "1",
      "2"
    ]
  },
  {
    "year": "2022",
    "cabin": "1",
    "months": [
      "4"
    ]
  },
  {
    "year": "2022",
    "cabin": "2",
    "months": [
      "1",
      "2"
    ]
  }
]

and this is the result I need:

{
  "2021": [
      {"cabin":1, "months": ["1", "2","4"]},
      {"cabin":2, "months": ["1", "2"]}
  ],
  "2022": [
      {"cabin":1, "months": ["1", "2","4"]},
      {"cabin":2, "months": ["1", "2"]}
  ]
}
1
  • let obj = {}, then obj[year] = [{'cabin': cabin, 'months': months}]; in your loop Commented Mar 12, 2021 at 23:55

2 Answers 2

1

This is a fairly standard group by situation. The snippet below uses reduce() to refactor your array, but you could place the logic directly in your function as it is: http://jsfiddle.net/83st9wgh/

const input = [{ "year": "2021", "cabin": "1", "months": ["1", "2"] }, { "year": "2021", "cabin": "1", "months": ["4"] }, { "year": "2021", "cabin": "2", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["1", "2"] }, { "year": "2022", "cabin": "1", "months": ["4"] }, { "year": "2022", "cabin": "2", "months": ["1", "2"] }];

const result = input.reduce((acc, { year, cabin, months }) => {
  const yearArray = (acc[year] ??= []);

  let cIndex = yearArray.findIndex(o => o.cabin === cabin);
  if (cIndex === -1) {
    cIndex = yearArray.push({ cabin, months: [] }) - 1;
  }

  const monthsArray = yearArray[cIndex].months;
  yearArray[cIndex].months = [...new Set(monthsArray.concat(months))];

  return acc;
}, {});

console.log(JSON.stringify(result, null, 2));

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

Comments

1

So, you're midway to the solution.

from what you have I wrote a grouping function:

const addUnique=(arr1,arr2)=>{
    arr2.forEach(item=>arr1.includes(item) || arr1.push(item))
    return arr1;
}

const grouped= obj.reduce((groups,item)=>{
  const yearItems=(groups[item.year]||[])
  const cabinItem=yearItems.find(({cabin})=>cabin===item.cabin)
  const newCabinItem=cabinItem||{cabin:item.cabin};
  newCabinItem.months=addUnique(newCabinItem.months||[],item.months);
    
  return {
    ...groups,
    [item.year]: cabinItem 
        ? yearItems.map(yearItem =>
          yearItem.cabin === item.cabin 
            ? newCabinItem 
            : yearItem)
        : yearItems.concat([newCabinItem])
    }
},{})

you can see it working here: http://jsfiddle.net/9huwkz5L/

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.