如何使用javascript按数组分组并确定行总数

如何使用javascript按数组分组并确定行总数,javascript,typescript,Javascript,Typescript,因此,在sql中,一个常见的操作是使用一个GROUPBY和having count=1的select语句 select bID from tableA groubBy bID having count(*) = 1 基本上,我期待做上述,但在打字脚本 我也希望在没有任何附加插件的情况下完成这项工作,所以我真的希望用javascript完成这项工作。基于一些谷歌搜索和访问,我发现.reduce函数或多或少是我所需要的(据我所知) 问题是我在这里得到的只是编译错误或转换错误。表示它的隐式类型为an

因此,在sql中,一个常见的操作是使用一个GROUPBY和having count=1的select语句

select bID from tableA groubBy bID having count(*) = 1
基本上,我期待做上述,但在打字脚本

我也希望在没有任何附加插件的情况下完成这项工作,所以我真的希望用javascript完成这项工作。基于一些谷歌搜索和访问,我发现.reduce函数或多或少是我所需要的(据我所知)

问题是我在这里得到的只是编译错误或转换错误。表示它的隐式类型为any或没有回调函数。。等等

我要做的是传入一个数组。按值对它们进行分组。然后看看有多少是他们的。如果计数等于1,则为满足该条件的每个值设置一个等于true的属性,然后退出该方法

这是我从网上得到的

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;
    }, []);
}
不管出于什么原因,人们喜欢在这里使用非常短的变量名,这让我很困惑。我不知道xs或rv是什么,也不知道它的意思,也不知道该变量的内部是什么,所以如果您能帮助解释我粘贴的代码,那可能就是我所需要的

再次感谢

PPS。一个快速的数据示例是

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

所以应该返回的是[{bId:1,isDeleted:false}{bId:2,isDeleted:false},{bId:4,isDeleted:false}]

下面是一个代码示例,说明了我可以做些什么

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

编辑:快速编辑,我为造成的混乱道歉。但是我写的语法是Typescript。我知道typescript是javascript,但在我最初的问题中我提到了javascript,因为我想避免混淆原型,因为这种方法不是最佳实践

您可以简化分组函数,并将该结果用于筛选,以获得数组中相同的分组对象,然后对其进行筛选,以仅获得长度为1的结果集。如有必要,将对象从阵列中取出

函数分组依据(数组、键){
返回数组.reduce((累加器,对象)=>{
var temp=累加器.find(数组=>数组[0][key]==对象[key]);
如果(临时){
温度推送(对象);
}否则{
累加器。推送([对象])
}
回流蓄能器;
}, []);
}
var数组=[{bID:1},{bID:1},{bID:2},{bID:1},{bID:3},{bID:4}],
结果=groupBy(数组“bID”)
.filter(({length})=>length==1)
.map(([v])=>v);

控制台日志(结果)您可以只按值排序并删除一行中出现两次的所有值,而不是在之后进行分组和筛选:

 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])
    );
 }

您应该可以使用一个reduce函数来完成此操作

然后你可以将其扩展到一个可重用的函数,就像其他答案所示

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)
}, [])}

你从哪里获得代码?@NinaScholz在Michael Sandino的评论中,在已标记为更正的响应下,每当我使用你的代码时,我都会收到一个类型错误。它会带着这个回来。无法读取未定义的属性“bID”,但我知道该属性是在调试和查看对象时定义的。@JTSLOMASTER08我进行了编辑以修复该问题,您可以尝试使用最新版本吗?是,不再出错。我编辑了我的问题,但我还有一个曲线球。现在,如果用户删除了一行。我不会删除它,我会翻转一个isdeleted标志。因此,我尝试使用您的代码执行此操作。“&&(!el.isDeleted===true)”但它仍然只返回2条记录。@jtslugmaster08所以您想完全忽略已删除的值吗?也许只是在做其他事情之前过滤掉它们?…就是这样。我不知道为什么我想不起那个lol,再次谢谢。当我调用你的方法时,我所要做的就是做一个myarray.filter(o=>!o.isDeleted),就是这样。看起来是这样的。var test=unique(myArray.filter(o=>!o.isDeleted),“bID”)/*我的附加代码在这里*/
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)
}, [])}