Lodash或与LINQ Group by等效的JavaScript,并选择FirstOrDefault()

时间:2019-05-06 14:07:55

标签: javascript typescript lodash

我有具有AuthorizationOrder的商店的列表,我将需要提取JavaScript中分组集合的firstOrDefault值。

eg: storeDto : { StoreNumber = 1 , Warehouse = 4201, AuthorizationOrder = 1 },
               { StoreNumber = 2 , Warehouse = 4201, AuthorizationOrder = 2 },
               { StoreNumber = 1 , Warehouse = 4202, AuthorizationOrder = 2 },
               { StoreNumber = 1 , Warehouse = 4203, AuthorizationOrder = 3 },
               { StoreNumber = 2 , Warehouse = 4207, AuthorizationOrder = 1 }

使用LINQ:

warehouseStoreList = warehouseStoreList.GroupBy(x => x.StoreNumber)
      .Select(g => g.OrderBy(x => x.AuthorizationOrder).FirstOrDefault()).ToList();


Result: { StoreNumber = 1 , Warehouse = 4201, AuthorizationOrder = 1 },
        { StoreNumber = 2 , Warehouse = 4207, AuthorizationOrder = 1 }

如何使用Lodash或JavaScript进行类似的操作以通过在store上分组来提取数据,在AuthorizationOrder上订购后获得第一个值。

此外,获取具有关联商店的仓库。请参阅使用LINQ实现的小提琴

提琴:https://dotnetfiddle.net/glC1ij

想用JavaScript或Lodash实现相同的目的。

3 个答案:

答案 0 :(得分:1)

您可以使用reduce根据StoreNumber进行分组。创建一个具有唯一每个唯一StoreNumber作为键的累加器,如下所示:

{
  "1": {
    "StoreNumber": 1,
    "Warehouse": 4201,
    "AuthorizationOrder": 1
  },
  "2": {
    "StoreNumber": 2,
    "Warehouse": 4207,
    "AuthorizationOrder": 1
  }
}

如果key不存在或当前AuthorizationOrder小于累加器的值,则更新值。然后使用Object.values()将值仅获取到数组:

const array = [{StoreNumber:1,Warehouse:4201,AuthorizationOrder:1},{StoreNumber:2,Warehouse:4201,AuthorizationOrder:2},{StoreNumber:1,Warehouse:4202,AuthorizationOrder:2},{StoreNumber:1,Warehouse:4203,AuthorizationOrder:3},{StoreNumber:2,Warehouse:4207,AuthorizationOrder:1}]

const grouped = array.reduce((acc, o) => {
  let group = acc[o.StoreNumber];
  
  if(!group || group.AuthorizationOrder > o.AuthorizationOrder)
    acc[o.StoreNumber] = o;

  return acc;
}, {})

console.log(Object.values(grouped))

答案 1 :(得分:1)

您可以按照以下步骤进行操作:

  • 在对象数组上应用reduce(),并将累加器设置为空对象{}
  • 对象的键将是storeNumber,值将是对象。
  • 检查特定键处已经存在的对象的AuthorizationOrder是否大于我们要迭代的元素的AuthorizationOrder,然后将该键的值更改为当前元素。否则不要更改它。
  • 最后使用Object.values()获取对象数组。

const arr = [{ StoreNumber:1 , Warehouse:4201, AuthorizationOrder:1 },
               { StoreNumber:2 , Warehouse:4201, AuthorizationOrder:2 },
               { StoreNumber:1 , Warehouse:4202, AuthorizationOrder:2 },
               { StoreNumber:1 , Warehouse:4203, AuthorizationOrder:3 },
               { StoreNumber:2 , Warehouse:4207, AuthorizationOrder:1 }]
               
const res = arr.reduce((ac,a) => {
  let ao = a.AuthorizationOrder
  let ao2 = (ac[a.StoreNumber] || {}).AuthorizationOrder || Infinity 
  if(ao < ao2) ac[a.StoreNumber] = a;
  return ac
},{});

console.log(Object.values(res))

答案 2 :(得分:0)

使用lodash / fp,您可以按StoreNumber对项目进行分组,然后将每个组映射到具有最小AuthorizationOrder值的项目:

const { flow, groupBy, map, minBy } = _

const fn = flow(
  groupBy('StoreNumber'),
  map(minBy('AuthorizationOrder'))
)

const array = [{StoreNumber:1,Warehouse:4201,AuthorizationOrder:1},{StoreNumber:2,Warehouse:4201,AuthorizationOrder:2},{StoreNumber:1,Warehouse:4202,AuthorizationOrder:2},{StoreNumber:1,Warehouse:4203,AuthorizationOrder:3},{StoreNumber:2,Warehouse:4207,AuthorizationOrder:1}]

const result = fn(array)

console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>