简体   繁体   中英

How to group by an array and determine total count of rows using javascript

So in sql a common thing to do is a select statement with a group by and then a having count =1 or what have you.

select bID from tableA groubBy bID having count(*) = 1

Essentially I am looking to do the above but in typescript.

I also would like to do it without any additional plugins so really I would like to do this in javascript. Based on some googling I have done as well as visiting SO I have found the .reduce function to be more or less what I need (as far as I know)

The problem is I get about here and all I get are compile errors or conversion errors. Saying that it has an implicit type of any or does not have a callback function of .. etc...

What I am trying to do is pass in an array. Group them by a value. Then see how many of them their are. If the count is equal to 1 set a property equal to true for each that meet that criteria, and then exit the method.

Here is what I got from the internet.

groupByArray(xs, key) {
    return xs.reduce(function (rv, x) {
        let v = key instanceof Function ? key(x) : x[key];
        let el = rv.find((r) => r && r.key === v);
        if (el) { el.values.push(x); } else { rv.push({ key: v, values: [x] }); }
        return rv;
    }, []);
}

PS. for whatever reason people like to use very short variable names here and it confuses me. I have no idea what xs or rv is or means or what is inside of that variable so if you could help explain the code I pasted as well that might be all I need.

Thanks again.

PPS. a quick data example would be

[{bID:1,isDeleted:false},{bID:1,isDeleted:true},{bID:2,isDeleted:false},{bID:1,isDeleted:true},{bID:3,isDeleted:false},{bID:3,isDeleted:false},{bID:4,isDeleted:false}]

so what should be returned is[{bId:1,isDeleted:false}{bID:2,isDeleted:false},{bID:4,isDeleted:false}]

Below is a code example of what I could get to work.

 var test = this.user2.scc.sA.reduce((a, b) => (a.Bid== b.Bid && !a.isDeleted) ? a : b);

Edit: Quick edit and I apologize for the confusion. But the syntax I am writing in is Typescript. I know typescript is javascript but in my original question I mentioned javascript because I wanted to avoid messing with prototypes as this method is not best practice.

Instead of grouping & filtering afterwards you could just sort by the value and remove all values that appear twice in a row:

 function unique(array, key) {
   return array
     .sort((a, b) => a[key] > b[key] ? 1 : -1)
     .filter((el, index) => 
       (index < 1 || el[key] !== array[index - 1][key]) &&
       (index >= array.length - 1 || el[key] !== array[index + 1][key])
    );
 }

That can be used as:

 unique([{bID:1},{bID:1},{bID:2},{bID:1},{bID:3},{bID:3},{bID:4}], "bID")

You could simplify the function for grouping and take that result for filtering to get same grouped objects in an array and then filter this for getting only the result sets with a length of one. If necessary take the obejects out of the array.

 function groupBy(array, key) { return array.reduce((accumulator, object) => { var temp = accumulator.find(array => array[0][key] === object[key]); if (temp) { temp.push(object); } else { accumulator.push([object]) } return accumulator; }, []); } var array = [{ bID: 1 }, { bID: 1 }, { bID: 2 }, { bID: 1 }, { bID: 3 }, { bID: 3 }, { bID: 4 }], result = groupBy(array, 'bID') .filter(({ length }) => length === 1) .map(([v]) => v); console.log(result); 

you should be able to do this with one reduce function.

and then you can extend that to a reusable function like the other answers show.

function groupUnique(data, key) {
    return data.reduce((accumulator, element) => {
    const targetIdx = accumulator.findIndex(el => el[key] === element[key]);
    if (targetIdx > -1) {
        return accumulator.splice(targetIdx, 1);
    }
    return accumulator.concat(element)
}, [])}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM