Репост как исправленная версия этого вопроса а>. Я просмотрел это, но это не помогло мне справиться с неизвестными вложениями массивов.
EDIT: добавлена информация о том, почему Lodash _.get
не работает. Вот Stackblitz. Есть библиотека npm, Object-Scan, которая будет работать, но я не могу Не заставить Angular работать с этим пакетом.
Это для компонента рендеринга столбцов в приложении Angular. Пользователь выбирает столбец для отображения, и этот столбец сопоставляется с тем, чем он является. Итак, в приведенном ниже примере, если пользователь выбирает отображение категорий, и они сопоставляются с интересами [категории], функция затем должна найти значения, соответствующие этому сопоставлению в данных.
Образец данных:
const response = {
id: "1234",
version: "0.1",
drinks: ["Scotch"],
interests: [
{
categories: ["baseball", "football"],
refreshments: {
drinks: ["beer", "soft drink"]
}
},
{
categories: ["movies", "books"],
refreshments: {
drinks: ["coffee", "tea", "soft drink"]
}
}
],
goals: [
{
maxCalories: {
drinks: "350",
pizza: "700"
}
}
]
};
Возможные сопоставления для этих данных: id
, version
, drinks
, interests[categories]
, interests[refreshments][drinks]
, goals[maxCalories][drinks]
, goals[maxCalories][pizza]
,
Требование: мне нужна рекурсивная функция, которая будет работать в Angular и принимать два аргумента: один для объекта данных response
, а вторая строка сопоставления селектора, которая будет возвращать применимые, потенциально вложенные значения, перебирая любые объекты и/или встречающиеся массивы. Строка сопоставления может иметь нотацию с точками или скобками. Читаемый, самодокументирующийся код очень желателен.
Например, на основе вышеуказанного объекта данных:
getValues("id", response);
должен вернуть["1234"]
getValues("version", response);
должен вернуть["0.1"]
getValues("drinks", response);
должно вернуть["Scotch"]
getValues("interests.categories", response)
должен вернуть["baseball", "football", "movies", "books"]
getValues("interests[refreshments][drinks]", response);
должно возвращать["beer", "soft drink", "coffee", "tea", "soft drink" ]
с учетом того, сколько элементов может быть в массивеinterests
.getValues("goals.maxCalories.drinks", response);
должно вернуть["350"]
Возвращаемые значения в конечном итоге будут дедуплицированы и отсортированы.
Оригинальная функция:
function getValues(mapping, row) {
let rtnValue = mapping
.replace(/\]/g, "")
.split("[")
.map(item => item.split("."))
.reduce((arr, next) => [...arr, ...next], [])
.reduce((obj, key) => obj && obj[key], row)
.sort();
rtnValue = [...new Set(rtnValue)]; //dedupe the return values
return rtnValue.join(", ");
}
Вышеупомянутое работает отлично, так же, как и получить Lodash: если вы передаете, например: "interests[0][refreshments][drinks]
, он работает отлично. Но сопоставление не знает о вложенных массивах и передает просто "interests[refreshments][drinks]"
, что приводит к undefined
. Необходимо учитывать любые последующие элементы массива.
getValues("interests[refreshments][drinks]", response);
недействителен. Элементы индекса могут быть только числами или строками в кавычках. - person vitaly-t   schedule 08.03.2021replace.split.map.reduce
преобразует входную строку во что-то более приемлемое:["interests", "refreshments", "drinks"]
В приведенном ниже ответе это обрабатывается гораздо более элегантно в однострочнике:query.split (/[[\].]+/g).filter (Boolean)
- person Joe H.   schedule 09.03.2021