1

Suppose I have a Javascript array like below.

const data = [   
    { group: 'A', name: 'SD', testid:1},    
    { group: 'B', name: 'FI',testid:2  },    
    { group: 'A', name: 'MM', testid:1 },   
    { group: 'B', name: 'CO', testid:2 },   
    { group: 'A', name:  'QW',  testid:1 } 
];

I want to get two specific properties(group and testid).

I would like to retrieve unique values for those properties in my end result. So my end result will be

{group:A,testid:1},{group:B,testid:2}

What I have tried so far is below.

  data.map(item=>item.group).

But this will give me only one property and without any distinct values How can I achieve this using latest ecmascript syntax in Javascript

shakz
  • 629
  • 3
  • 14
  • 38
  • Does the same group always have the same testid? If not, should `{group: A, testid: 2}` be in the result? – Barmar Jul 22 '20 at 17:37
  • Yes. Same group will always have same testid – shakz Jul 22 '20 at 17:40
  • Create an object to hold the results. Loop through the array, adding an object with `group` and `testid` to the result object, using `group` as the key. When you're done, the values of the result object will be your unique set. – Barmar Jul 22 '20 at 17:41
  • https://stackoverflow.com/questions/18773778/create-array-of-unique-objects-by-property – Barmar Jul 22 '20 at 17:43

3 Answers3

1

you can reduce the array and check every time if the pair exists:

data.reduce((prev, el) =>{
    if(prev.some(o => o.group == el.group && o.testid == el.testid))
         return prev;
    return [...prev, {group:el.group, testid:el.testid}]
}, [])

const data = [   
    { group: 'A', name: 'SD', testid:1},    
    { group: 'B', name: 'FI',testid:2  },    
    { group: 'A', name: 'MM', testid:1 },   
    { group: 'B', name: 'CO', testid:2 },   
    { group: 'A', name:  'QW',  testid:1 } 
];
let result = data.reduce((prev, el) =>{
    if(prev.some(o => o.group == el.group && o.testid == el.testid))
         return prev;
    return [...prev, {group:el.group, testid:el.testid}]
}, []);

console.log(result);
Alberto Sinigaglia
  • 12,097
  • 2
  • 20
  • 48
  • @shakz : this answer may work [***up to 40 times slower***](https://jsbench.me/v0kcxogbky/1) than [the fastest among suggested](https://stackoverflow.com/a/63040204/11299053). – Yevhen Horbunkov Jul 22 '20 at 18:09
  • @YevgenGorbunkov he hasn't asked for an efficient way to do it, you can so the same in a sort of HashMap check every time check if exists the current one or no, but i don't see why we should care about performance if he hadn't asked for it – Alberto Sinigaglia Jul 22 '20 at 18:11
  • It's not about performance in the first place, it's about promoting solutions with optimal algorithms and robust implementation. My solution is 40x faster not only because of appropriate tooling, but due to optimal underpinning algorithm. So, your answer to *`why we should care?`* is 'To let other users who come across this thread, and to whom performance **does matter** not to suffer because of CPU cycles wasted, just because they were lazy enough not to scroll farther than accepted answer'. – Yevhen Horbunkov Jul 22 '20 at 18:18
  • @YevgenGorbunkov oh and btw, if you mention that it can be 40x slower, than it has the same complexity, since g(n) = O(f(n)) -> lm n->+inf g(n) / C * f(n) = 0, soooooooooo if it is 40 times slower, means that C is 40, and so it has the same complexity, and if you want i can tell you more about algorithm complexity – Alberto Sinigaglia Jul 22 '20 at 18:18
  • @YevgenGorbunkov go crying under your ugly answer, you will find that efficiency in code is not the only thing that matters, and if you are really talking about linear difference in algorithm in JS, you have probably missed that you are talking already about a language that is 10 times slower than many others, and you are absolutely free to develop this code in web assembly so that your code can be even more uglier but faster, have a nice day – Alberto Sinigaglia Jul 22 '20 at 18:21
0

You can loop over it and get the desired result.

result = []
data.forEach(x=>{
    if(!result.some(y=>y.group===x.group && x.testid===y.testid)){
        result.push({group:x.group,testid:x.testid});
    }
});
0

Use forEach loop and build an object with keys as uniq_id. After the traverse, return Object.values of the above object.

const convert = (arr) => {
  const res = {};
  arr.forEach(({group, testid}) => {
    // change uniq_id based on requirement
    const uniq_id = `${group}-${testid}`;
    res[uniq_id] = { group, testid};
  });
  return Object.values(res);
}

const data = [   
    { group: 'A', name: 'SD', testid:1},    
    { group: 'B', name: 'FI',testid:2  },    
    { group: 'A', name: 'MM', testid:1 },   
    { group: 'B', name: 'CO', testid:2 },   
    { group: 'A', name:  'QW',  testid:1 } 
];

console.log(convert(data));
Siva K V
  • 10,561
  • 2
  • 16
  • 29
  • I would say, hyphen is a risky delimiter as it may cause `{group: 'A-B', testid: 'C'}` and `{group: 'A', testid: 'B-C'}` recognized as the same record unexpectedly – Yevhen Horbunkov Jul 22 '20 at 17:49