Javascript словарь словарей в словарь на основе 2-го уровня ключа - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть словарь словарей:

var dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

И мне нужно сократить его до словаря, подобного этому:

var dicX = {
  a : "ax"
  b : "bx"
}

для х, или следующее для у.

var dicY = {
  a : "ay"
  b : "by"
}

Теперь я знаю, что это можно сделать с помощью карты и операций сокращения:

let mapped  = Object.keys(dic1).map((k)=>{return {key:k,x:dic1[k].x,y:dic1[k].y}})

let dicX_2 = mapped.reduce((accumulator, current) => {
  accumulator[current.key] = current.x;
  return accumulator;
},{});

let dicY_2 = mapped.reduce((accumulator, current) => {
  accumulator[current.key] = current.y;
  return accumulator;
},{});

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

Ответы [ 6 ]

0 голосов
/ 16 февраля 2019

Здесь у вас есть одно общее решение.Вы создаете метод, который получает словарь и второй уровень key и возвращает ожидаемый объект.

var dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

const mapDictionary = (dic, innerProp) =>
{
    return Object.entries(dic).reduce(
        (acc, [key, obj]) => (acc[key] = obj[innerProp], acc),
        {}
    );
}

console.log(mapDictionary(dic1, "x"));
console.log(mapDictionary(dic1, "y"));
0 голосов
/ 16 февраля 2019

Один лайнер:

let dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

let {a: dicX} = {a: { a: dic1.a.x, b: dic1.b.x }}, {a: dicY} = {a: { a: dic1.a.y, b: dic1.b.y }}
0 голосов
/ 16 февраля 2019

Вот одна строка в простом JavaScript:

const dic1 = {
  a : { x : "ax", y : "ay" },
  b : { x : "bx", y : "by" }
};

const dicX = Object.entries(dic1).reduce((a, [k, v]) => ({ ...a, [k]: v.x }), {});
const dicY = Object.entries(dic1).reduce((a, [k, v]) => ({ ...a, [k]: v.y }), {});

console.log(dicX);
console.log(dicY);

Если вы сделаете это функцией, она будет иметь длину 1,25 строки:

const dic1 = {
  a : { x : "ax", y : "ay" },
  b : { x : "bx", y : "by" }
};

const dic = (d, p) =>
  Object.entries(d).reduce((a, [k, v]) => ({ ...a, [k]: v[p] }), {});

console.log(dic(dic1, 'x'));
console.log(dic(dic1, 'y'));

Вот еще один способ без reduce и использования Object.assign для объединения свойств из каждого внутреннего словаря, но это решение немного длиннее:

const dic = (d, p) =>
      Object.assign({}, ...Object.entries(d).map(([k, v]) => ({ [k]: v[p] })));
0 голосов
/ 16 февраля 2019

Существует много подходов для получения одинакового результата.Можно быть следующим:

var dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

const all = Object.values (dic1).flatMap (Object.entries)

const xs = Object.fromEntries (all.filter (([a]) => a == 'x').map (([a, b]) => [b[0], b]))
const ys = Object.fromEntries (all.filter (([a]) => a == 'y').map (([a, b]) => [b[0], b]))

console.log (xs)
console.log (ys)

Вот еще лучший вариант:

var dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

const flatten = (by, dict) => 
    Object.fromEntries (
        Object.entries (dict)
              .map (([x, y]) => [x, y[by]])
    )
    
const xs = flatten ('x', dic1)
const ys = flatten ('y', dic1)

console.log ('xs', xs)
console.log ('ys', ys)
0 голосов
/ 16 февраля 2019

Используя Ramda , ваша однострочная строка будет выглядеть так:

const {map, prop} = R;

var dic1 = {
  a : {
    x : "ax",
    y : "ay"
  },
  b : {
    x : "bx",
    y : "by"
  }
}

console.log(map(prop('x'), dic1));
console.log(map(prop('y'), dic1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
0 голосов
/ 16 февраля 2019

Нет, для этого нет единой строки, хотя map в вашем коде выглядит довольно ненужным.Вы можете просто сделать это в самом обратном вызове reduce.

Однако я бы порекомендовал вообще не использовать reduce, а во избежание дублирования кода сделать простую вспомогательную функцию:

function mapObject(o, f) {
    const r = {};
    for (const p in o) // you could use `reduce` here as well, but it doesn't become simpler
        r[p] = f(o[p], p);
    return r;
}

Тогда используйте это как

const dicX = mapObject(dic1, inner => inner.x);
const dicY = mapObject(dic1, inner => inner.y);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...