-2

Assuming an array

[
{id: 1, label: "Hello"},
{id: 2, label: "World"},
{id: 3, label: "Hello"},
{id: 4, label: "Sunshine"},
{id: 5, label: "Hello"}
]

I need output like below

[
{id: 1~3~5, label: "Hello"},
{id: 2, label: "World"},
{id: 4, label: "Sunshine"}
]

Please help to provide the solution using javascript

user1124166
  • 1
  • 1
  • 1
  • 5
  • 1
    What have you tried? And what should `1~4~5` (I guess `1~3~5`) be? – A_A Aug 17 '21 at 17:34
  • Yes, you are correct. sorry for typo. – user1124166 Aug 17 '21 at 17:37
  • StackOverflow is not a code writing service. You are expected to show us your best attempt at writing the solution. See [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). Please [edit your question](https://stackoverflow.com/posts/68821709/edit) to show us your code. – kmoser Aug 17 '21 at 17:45
  • Familiarize yourself with [how to access and process nested objects, arrays or JSON](/q/11922383/4642212) and how to [create objects](//developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer) and use the available static and instance methods of [`Object`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods) and [`Array`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array#Static_methods). – Sebastian Simon Aug 17 '21 at 18:31

5 Answers5

2

You can use Array.reduce:

const arr = [
  {id: 1, label: "Hello"},
  {id: 2, label: "World"},
  {id: 3, label: "Hello"},
  {id: 4, label: "Sunshine"},
  {id: 5, label: "Hello"}
]

const res = arr.reduce((a, itm) => {
  var f = a.filter(e => e.label == itm.label);
  f.length > 0 ? f[0].id += "~" + itm.id : a.push(itm)
  return a;
}, [])
console.log(res)
Spectric
  • 30,714
  • 6
  • 20
  • 43
0

What about that?

const arr = [
  { id: 1, label: "Hello" },
  { id: 2, label: "World" },
  { id: 3, label: "Hello" },
  { id: 4, label: "Sunshine" },
  { id: 5, label: "Hello" },
];

// filter array from a key
const filterDuplicates = (arr, key) => {
  const values = new Set();
  return arr.filter((item) => {
    const value = item[key];
    if (values.has(value)) {
      return false;
    }
    values.add(value);
    return true;
  });
};

// the filtered array
const filtered = filterDuplicates(arr, "label");

console.log(filtered);
Ludal
  • 110
  • 1
  • 7
0

I would also use Array.prototype.reduce, but coupled with a Set.

Like:

const inputArray = [
  { id: 1, label: "Hello" },
  { id: 2, label: "World" },
  { id: 3, label: "Hello" },
  { id: 4, label: "Sunshine" },
  { id: 5, label: "Hello" },
];

// Remove duplicates.
const uniqueLabelSet = new Set(inputArray.map(inputObject => inputObject.label));

const outputArray = Array.from(uniqueLabelSet).map((uniqueLabel) => {
  return {
    label: uniqueLabel,
    id: inputArray
      .filter((inputObject) => inputObject.label === uniqueLabel)
      .reduce((id, inputObject) => {
        return id ? id += `~${inputObject.id}` : inputObject.id;
      }, '')
  }
});

console.log(outputArray)
Adam Patterson
  • 958
  • 7
  • 13
0

Creating a general groupBy helper would simplify things quite a bit.

function groupBy(iterable, fn) {
  const groups = new Map();
  for (const item of iterable) {
    const key = fn(item);
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key).push(item);
  }
  return groups;
}

With the above helper you can use the following transform your data.

const result = Array.from(groupBy(data, item => item.label))
  .map(([label, items]) => ({ id: items.map(item => item.id), label }));

This does the following to your data.

// group the items based on label
let result = groupBy(data, item => item.label);
//=> { // <- Map instance displayed as plain JS object
//   "Hello": [
//     {id: 1, label: "Hello"},
//     {id: 3, label: "Hello"},
//     {id: 5, label: "Hello"}
//   ],
//   "World": [
//     {id: 2, label: "World"}
//   ],
//   "Sunshine": [
//     {id: 4, label: "Sunshine"}
//   ]
// }

// change the Map instance into an Array so we can use .map()
result = Array.from(result);
//=> [
//   ["Hello", [
//     {id: 1, label: "Hello"},
//     {id: 3, label: "Hello"},
//     {id: 5, label: "Hello"}
//   ]],
//   ["World", [
//     {id: 2, label: "World"}
//   ]],
//   ["Sunshine", [
//     {id: 4, label: "Sunshine"}
//   ]]
// ]

// convert the array into the desired format using .map()
result = result.map(([label, items]) => ({ id: items.map(item => item.id), label }));
//=> [
//   { id: [1,3,5], label: "Hello" },
//   { id: [2], label: "World" },
//   { id: [4], label: "Sunshine" },
// ]

I'm not quite sure why you are looking for the 1~3~5 format, using an array seems more logical. If you however insist on using 1~3~5 change:

items.map(item => item.id)
// into
items.map(item => item.id).join("~")

const data = [
  {id: 1, label: "Hello"},
  {id: 2, label: "World"},
  {id: 3, label: "Hello"},
  {id: 4, label: "Sunshine"},
  {id: 5, label: "Hello"}
];

const result = Array.from(groupBy(data, item => item.label))
  .map(([label, items]) => ({ id: items.map(item => item.id), label }));

console.log(result);


function groupBy(iterable, fn) {
  const groups = new Map();
  for (const item of iterable) {
    const key = fn(item);
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key).push(item);
  }
  return groups;
}

References:

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
0

var arr = [{
    id: 1,
    label: "Hello"
  },
  {
    id: 2,
    label: "World"
  },
  {
    id: 3,
    label: "Hello"
  },
  {
    id: 4,
    label: "Sunshine"
  },
  {
    id: 5,
    label: "Hello"
  }
];

//Variable declaration
var resultArr = [];
var current = null;
var flags = [], uniqueLabelArr = [];

//Get Unique label values array
for (var i = 0; i < arr.length; i++) {
  if (flags[arr[i].label]) continue;
  flags[arr[i].label] = true;
  uniqueLabelArr.push(arr[i].label);
}

// Iterate the input array for all unique labels
for (var i = 0; i < uniqueLabelArr.length; i++) {
  current = uniqueLabelArr[i];
  var mergedId = '';
  for (var j = 0; j < arr.length; j++) {
    if (arr[j].label == current) {
        if(mergedId == '')
        mergedId = arr[j].id;
      else
        mergedId = mergedId + '~' + arr[j].id;
    }
  }
  //Push the result object to final array
  resultArr.push({
    id: mergedId,
    label: current
  });
}
console.log(resultArr);
Reishabh
  • 167
  • 4
  • 8