使用lodash将GroupBy与lodash结合使用时出现问题,试图正确格式化数组

时间:2019-08-05 17:03:21

标签: javascript arrays lodash

我想获取一个用户列表,并将其归类到要由我的应用呈现的新数组中。

我得到的是什么

OnlineList = [
  {
    "Role": "Adjuster",
    "AccountId": "4",
    "UserId": "1e72d58e",
    "DisplayName": "Big Bob",
  },
  {
    "Role": "Adviser",
    "AccountId": "5",
    "UserId": "a0daba73",
    "DisplayName": "Sassy Sally",
  }
];

我想要什么结果?

OnlineUsers = {
  "Dealership": [
    {
      "Role": "Adviser",
      "AccountId": "Dealership",
      "UserId": "a0daba73",
      "DisplayName": "Sassy Sally",
    }
  ],
  "ClaimsCo": [
    {
      "Role": "Adjuster",
     "AccountId": "ClaimsCo",
      "UserId": "1e72d58e",
      "DisplayName": "Big Bob",
    }
  ]
}

我得到的结果:

OnlineUsers = {
  "5": [    <----------- Problem
    {
      "Role": "Adviser",
      "AccountId": "5",   <----------- Problem
      "UserId": "a0daba73",
      "DisplayName": "Sassy Sally",
    }
  ],
  "ClaimsCo": [
    {
      "Role": "Adjuster",
      "AccountId": "Dealership",
      "UserId": "1e72d58e",
      "DisplayName": "Big Bob",
    }
  ]
}

这是我设置用来复制问题的JFiddle:http://jsfiddle.net/vc4mjwx3/20/

我的代码:

// loaded from API Request into array
var OnlineList = [];
//  Sorted and ordered for display
var OnlineUsers = [];
OnlineList = [
  {
    "Role": "Adjuster",
    "AccountId": "4",
    "UserId": "1e72d58e",
    "DisplayName": "Big Bob",
  },
  {
    "Role": "Adviser",
    "AccountId": "5",
    "UserId": "a0daba73",
    "DisplayName": "Sassy Sally",
  }
];

// GroupBy function: https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects/43215522
let groupBy = function(xs, key) {
	return xs.reduce(function(rv, x) {
      (rv[x[key]] = rv[x[key]] || []).push(x);
      return rv;
  }, {});
};

// Simulates a get by Id API service
let accountService = (id) => {
	if (id == 4) {
  return "ClaimsCo."
  }
 	else  {
  return "Dealership"
  }
}

// pass in AccountId
let getAccountName = function(int) {
  var accountName = "";
  //get AccountName from Id
  accountName = accountService(int);
    for(var x=0; x < OnlineList.length; x++){
    // check for AccountId
      if(OnlineList[x].hasOwnProperty('AccountId')){
      // Set AccountId value to AccountName
      OnlineList[x].AccountId = accountName;
      // Group results and set to OnlineUsers array
      OnlineUsers = groupBy(OnlineList, 'AccountId');
      break;
     }
	}
};

// Go into first element of array and get AccountId value
var id = _.get(OnlineList[0], "AccountId");
// Convert value to int
var int = parseInt(id,10);
// Pass into function that gets AccountName from AccountId and replaces AccountId in that element of OnlineList array
getAccountName(int);

//result
console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

总体而言,我希望我的代码像这样运行:

  1. 遍历OnlineList中的每个元素
  2. 对于该元素,获取AccountId值
  3. 将该AccountId值传递到将返回AccountName的服务中
  4. 用AccountName替换该元素的AccountId
  5. 对OnlineList数组中的所有其他元素重复
  6. 处理完所有AccountId / AccountName后,使用GroupBy通过AccountId属性对OnlineList数组的所有元素进行分组,并将它们设置为名为OnlineUsers的新数组。

3 个答案:

答案 0 :(得分:1)

    // loaded from API Request into array
var OnlineList = [];
//  Sorted and ordered for display
var OnlineUsers = [];
OnlineList = [{
    "Role": "Adjuster",
    "AccountId": "4",
    "UserId": "1e72d58e",
    "DisplayName": "Big Bob",
  },
  {
    "Role": "Adviser",
    "AccountId": "5",
    "UserId": "a0daba73",
    "DisplayName": "Sassy Sally",
  }
];

// GroupBy function: https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects/43215522
let groupBy = function(xs, key) {
  return xs.reduce(function(rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
  }, {});
};

// Simulates a get by Id API service
let accountService = (id) => {
  if (id == 4) {
    return "ClaimsCo."
  } else {
    return "Dealership"
  }
}

// pass in AccountId
let getAccountName = function(int, element) {
  var accountName = "";
  //get AccountName from Id
  accountName = accountService(int);
  // check for AccountId
  if (OnlineList[element].hasOwnProperty('AccountId')) {
    // Set AccountId value to AccountName
    OnlineList[element].AccountId = accountName;
    // Group results and set to OnlineUsers array
    OnlineUsers = groupBy(OnlineList, 'AccountId');
  }
};

for (var x = 0; x < OnlineList.length; x++) {
  var id = _.get(OnlineList[x], "AccountId");
  var int = parseInt(id, 10);
  getAccountName(int, x);

}
// Go into first element of array and get AccountId value


//result
console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

我不得不将计数从for循环传递给getAccountName函数。现在它可以正常工作了。希望这对某人有帮助。

答案 1 :(得分:1)

您需要映射AccountId号并将其替换为名称,然后按名称分组。我使用_.flow()创建管道:

const { flow, partialRight: pr, map, groupBy } = _;

// Simulates a get by Id API service
const accountService = (id) => id === 4 ? "ClaimsCo." : "Dealership";

const fn = flow(
  pr(map, o => ({ ...o, AccountId: accountService(+o.AccountId) })), // replace AccountId with name the + operator converts to number
  pr(groupBy, 'AccountId'), // group by the new AccountId
)

const OnlineList = [{"Role":"Adjuster","AccountId":"4","UserId":"1e72d58e","DisplayName":"Big Bob"},{"Role":"Adviser","AccountId":"5","UserId":"a0daba73","DisplayName":"Sassy Sally"}];

//result
const OnlineUsers = fn(OnlineList);

console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

使用lodash / fp的更短版本:

const { flow, map, groupBy } = _;

// Simulates a get by Id API service
const accountService = (id) => id === 4 ? "ClaimsCo." : "Dealership";

const fn = flow(
  map(o => ({ ...o, AccountId: accountService(+o.AccountId) })), // replace AccountId with name the + operator converts to number
  groupBy('AccountId'), // group by the new AccountId
)

const OnlineList = [{"Role":"Adjuster","AccountId":"4","UserId":"1e72d58e","DisplayName":"Big Bob"},{"Role":"Adviser","AccountId":"5","UserId":"a0daba73","DisplayName":"Sassy Sally"}];

//result
const OnlineUsers = fn(OnlineList);

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

答案 2 :(得分:1)

问题已经回答,但是我想分享一个不同的解决方案。

我最近创建了一个在JavaScript中进行数组分类的库,名为categorize

这是使用它的解决方案:

const { categorize } = require("categorize");    

const onlineList = [
  {
    "Role": "Adjuster",
    "AccountId": "4",
    "UserId": "1e72d58e",
    "DisplayName": "Big Bob",
  },
  {
    "Role": "Adviser",
    "AccountId": "5",
    "UserId": "a0daba73",
    "DisplayName": "Sassy Sally",
  }
];

const categories = [
  { name: "Dealership", filter: ({ AccountId }) => AccountId === "4" },
  { name: "ClaimsCo", filter: ({ AccountId }) => AccountId === "5" },
];

const onlineUsers = categorize(onlineList, categories);

onlineUsers 变量将包含此对象:

{
  "Dealership": [
    {
      "Role": "Adjuster",
      "AccountId": "4",
      "UserId": "1e72d58e",
      "DisplayName": "Big Bob"
    }
  ],
  "ClaimsCo": [
    {
      "Role": "Adviser",
      "AccountId": "5",
      "UserId": "a0daba73",
      "DisplayName": "Sassy Sally"
    }
  ]
}