Как рекурсивно разделить / сгладить объект с помощью массивов - PullRequest
1 голос
/ 10 июля 2020

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

  • Если значение не является массивом, он должен вернуть объект как есть.
  • Если есть значение, которое является пустым массивом, оно должно вернуть объект как есть, но заменить это значение массива пустой строкой
  • Если есть несколько значений массива, он должен вернуть сплющенное разделение объект. Например, если есть объект с такими массивами, как:
{
    "wq": "e2201b13-aa03-4044-b4e3-1ecb25ef5083",
    "we": "2019-08-19T00:00:00",
    "er": "2019-09-18T00:00:00",
    "rt": "PAID",
    "ty": "300.00",
    "yu": "27.27",
    "ui": "272.73",
    "io": "0",
    "op": "300.00",
    "pa": "8df30d22-5af3-4d61-a420-566ccdad8cdf",
    "as": "AUD",
    "sd": false,
    "df": false,
    "fg": "2019-12-04T19:57:48",
    "gh": "2019-09-16T00:00:00",
    "hj": "0",
    "jk": [
        "6c9809af-269b-4b86-8b07-78c83a12bd18",
        "6c9809af-269b-4b86-8b07-78c83a12bd19"
    ],
    "lk": [
        '112',
        '111',
    ],
    "zx": null,
    "xc": "",
    "vb": []
}

, он должен возвращать массив с 4 объектами для всех их перестановок. Где значения lk, jk и vb - строки. vb всегда будет пустым, поскольку это пустой объект. Было бы точно так же, если бы в исходном объекте vb была такая '', т.е. пустая строка. 4 объекта, потому что есть 2 массива по 2 объекта в каждом. 2 ^ 2 = 4. Если, например, vb также имеет 2 объекта, тогда будет 2 ^ 3 = 8 объектов со всеми другими ключами такими же, но упомянутые 3 ключа в виде строк.

  • Значения внутри массивов неизвестны. Таким образом, это может быть произвольное количество значений od в диапазоне от 0 до n
  • Ключи в исходном объекте, которые могут быть массивами, неизвестны. Следовательно, ему необходимо рекурсивно перемещаться.
  • Значения в исходном объекте также могут быть нулевыми или {} объектами, которые можно игнорировать.

До сих пор я написал такой стартер что:

const result = [];
const reserve = {};

Object.keys(source).forEach((key) => {
    if (source[key] instanceof Object) {
        // const isArr = Array.isArray(source[key]);
        source[key].forEach((element) => {
            result.push({
                ...source,
                [key]: element
            });
        });
    } else {
        reserve[key] = source[key]
    }
})

console.log(result)
// console.log(reserve)
// console.log(result.map(i => Object.assign({}, i, reserve)))

Это в некоторой степени дает мне желаемый результат, но все еще требует доработки. Любые рекомендации и предложения приветствуются.

1 Ответ

1 голос
/ 10 июля 2020

Предполагая, что вы хотите получить декартово произведение и сохранить пустые массивы как одно значение, вы можете следить за этими данными.

Вы можете взять рекурсивную функцию, которая разделяет все пары ключ / значение и строить новое декартово произведение путем перебора значений, если массив с объектами снова вызывает getCartesian и строит новые объекты.

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) && v.length ? v : [v]).forEach(w =>
                (w && typeof w === 'object' && (!Array.isArray(w) || w.length) ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

var data = { wq: "e2201b13-aa03-4044-b4e3-1ecb25ef5083", we: "2019-08-19T00:00:00", er: "2019-09-18T00:00:00", rt: "PAID", ty: "300.00", yu: "27.27", ui: "272.73", io: "0", op: "300.00", pa: "8df30d22-5af3-4d61-a420-566ccdad8cdf", as: "AUD", sd: false, df: false, fg: "2019-12-04T19:57:48", gh: "2019-09-16T00:00:00", hj: "0", jk: ["6c9809af-269b-4b86-8b07-78c83a12bd18", "6c9809af-269b-4b86-8b07-78c83a12bd19"], lk: ["112", "111"], zx: null, xc: "", vb: [] };

console.log(getCartesian(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
...