Конвертировать массив сотрудников в словарь - PullRequest
0 голосов
/ 05 ноября 2019

Поэтому я использую библиотеку 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.

Ответы [ 4 ]

1 голос
/ 05 ноября 2019

короткая версия 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);
1 голос
/ 05 ноября 2019

Я думаю, что вы путаете массив объектов со словарем. Я включил обе версии ниже, чтобы показать разницу.

То, что вы хотите сделать с данными, это отобразить их, а не уменьшить.

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 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; }
1 голос
/ 05 ноября 2019

В JavaScript массив строго всегда численно индексируется структурой. Итак, .toArray соблюдает это. В PHP массив ближе к тому, что JavaScript считает простыми объектами.


При использовании этой библиотеки LINQ JavaScript

Вы можете использовать метод .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"
}
*/

Используя деструктуризацию, селекторы ключа / значения могутбыть преобразован в:

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

Если вы используете эту библиотеку для операций LINQ , вам нужно немного изменить синтаксис:

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"
}
*/
1 голос
/ 05 ноября 2019

Вы можете использовать reduce для достижения этой цели:

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

Или с более короткой версией, используя распространение объекта:

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