将员工数组转换为字典

Convert array of employees to Dictionary

所以我正在使用 LinqJS 库来实现以下目标:

    var allEmployees = [
        {
            "Id": 1374,
            "FirstName": "John",
            "LastName": "Doe"
        },
        {
            "Id": 1375,
            "FirstName": "Jane",
            "LastName": "Doe"
        }
    ];
    var employeeDictionary = Enumerable.from(allEmployees).toDictionary("$.Id", "$.FirstName+' '+$.LastName").toEnumerable().toArray();

employeeDictionary序列化为JSON时,我得到以下格式:

[
  {
    "key": 1374,
    "value": "John Doe"
  },
  {
    "key": 1375,
    "value": "Jane Doe"
  }
]

我不希望我的数据采用这种格式,我希望采用这种格式:

{
  "1374": "John Doe",
  "1375": "Jane Doe"
}

我在 PHP 中使用 YaLinqo 写了类似的东西,它给了我需要的结果:

echo json_encode(from($employees)->toDictionary('$v["Id"]', '$v["FirstName"]." ".$v["LastName"]')->toArray());

但是,我希望能够在我的 JavaScript 中实现这一点。

您可以使用 reduce 来实现:

employeeDictionary.reduce((acc, employee) => {
  acc[employee.key] = employee.value;
  return acc
}, {})

或使用对象传播的较短版本:

employeeDictionary.reduce((acc, employee) => ({
  ...acc,
  [employee.key]: employee.value
}), {})

我认为您将对象数组与字典混淆了。我在下面包含了两个版本以显示差异。

您想对数据做的是映射它,而不是减少它。

let allEmployees = [
  { "Id": 1374, "FirstName": "John", "LastName": "Doe" },
  { "Id": 1375, "FirstName": "Jane", "LastName": "Doe" }
];

let defaultOptions = {
  keyField: 'Id',
  valueFn: (emp) => `${emp['FirstName']} ${emp['LastName']}`
};

console.log('Dictionary', toDictionary(allEmployees, defaultOptions));
console.log('Pairs', toPairs(allEmployees, defaultOptions));

function toDictionary(list, options) {
  let opts = Object.assign({ keyField: 'key', valueField: 'value' }, options);
  return list.reduce((dict, item) => (Object.assign(dict, {
    [item[opts.keyField]] : opts.valueFn ? opts.valueFn(item) : item[opts.valueField]
  })), {});
}

function toPairs(list, options) {
  let opts = Object.assign({ keyField: 'key', valueField: 'value' }, options);
  return list.map((item) => ({
    key   : item[opts.keyField],
    value :  opts.valueFn ? opts.valueFn(item) : item[opts.valueField]
  }));
}
.as-console-wrapper { top: 0; max-height: 100% !important; }


这是一个列表包装器 class。

class ListWrapper {
  constructor(list, options) {
    this.list       = list;
    this.keyField   = options.keyField   || 'key'
    this.valueField = options.valueField || 'value'
    this.valueFn    = options.valueFn               /* optional */
  }
  toPairs() {
    return this.list.map(e=>({key:e[this.keyField],value:this.valueFn?this.valueFn(e):e[this.valueField]}));
  }
  toDictionary() {
    return this.list.reduce((d,e)=>(Object.assign(d,{[e[this.keyField]]:this.valueFn?this.valueFn(e):e[this.valueField]})),{});
  }
}

let allEmployees = [
  { "Id": 1374, "FirstName": "John", "LastName": "Doe" },
  { "Id": 1375, "FirstName": "Jane", "LastName": "Doe" }
];

let listWrapper = new ListWrapper(allEmployees, {
  keyField: 'Id',
  valueFn: (emp) => `${emp['FirstName']} ${emp['LastName']}`
});

console.log('Dictionary', listWrapper.toDictionary());
console.log('Pairs', listWrapper.toPairs());
.as-console-wrapper { top: 0; max-height: 100% !important; }

在JavaScript中,数组是严格的始终是数字索引结构。所以,.toArray 遵守这一点。在 PHP 中,数组更接近于 JavaScript 认为的普通对象。


如果使用 this LINQ JavaScript library

您可以使用 .toObject 方法生成您格式的对象 - 您需要传入两个函数 - 一个键选择器和一个值选择器,以便使用正确的数据构建对象:

var allEmployees = [
    {
        "Id": 1374,
        "FirstName": "John",
        "LastName": "Doe"
    },
    {
        "Id": 1375,
        "FirstName": "Jane",
        "LastName": "Doe"
    }
];
var employeeDictionary = Enumerable.from(allEmployees)
  .toDictionary("$.Id", "$.FirstName+' '+$.LastName")
  .toEnumerable()
  .toObject(entry => entry.key, entry => entry.value);

/* output:
{
  "1374": "John Doe",
  "1375": "Jane Doe"
}
*/

使用解构,key/value 选择器可以转换为:

.toObject(({key}) => key, ({value}) => value);

如果使用this library for LINQ operations,则需要稍微更改语法:

var allEmployees = [
    {
        "Id": 1374,
        "FirstName": "John",
        "LastName": "Doe"
    },
    {
        "Id": 1375,
        "FirstName": "Jane",
        "LastName": "Doe"
    }
];
var employeeDictionary = Enumerable.From(allEmployees)
  .ToDictionary("$.Id", "$.FirstName+' '+$.LastName")
  .ToEnumerable()
  .ToObject("$.Key", "$.Value");

/* output:
{
  "1374": "John Doe",
  "1375": "Jane Doe"
}
*/

一个简短的 linq 版本

var allEmployees = [{ Id: 1374, FirstName: "John", LastName: "Doe" }, { Id: 1375, FirstName: "Jane", LastName: "Doe" }],
    employeeDictionary = Enumerable.From(allEmployees)
        .Select("$ => { key: $.Id, value: $.FirstName + ' ' + $.LastName }")
        .ToObject("$.key", "$.value");
    
console.log(employeeDictionary);
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>

具有解构和 Object.fromEntries 的简短方法。

var allEmployees = [{ Id: 1374, FirstName: "John", LastName: "Doe" }, { Id: 1375, FirstName: "Jane", LastName: "Doe" }],
    employeeDictionary = Object.fromEntries(
        allEmployees.map(({ Id, FirstName, LastName }) =>
            [Id, [FirstName, LastName].join(' ')])
    );
    
console.log(employeeDictionary);