Группировать массивы по родительскому идентификатору объекта Ramda - PullRequest
1 голос
/ 03 ноября 2019

Нужна помощь сообщества Ramda ... У меня есть массив объектов, который мне нужно отсортировать по "chapter_id", и после сортировки просто удалите "chapter_id":

const stuff = [
  { id: 1, title: "hello world", chapter_id: "4321" },
  { id: 2, title: "new title", chapter_id: "21" },
  { id: 3, title: "...", chapter_id: "33" },
  { id: 4, title: "huh!?", chapter_id: "14" },
  { id: 5, title: "From Earth", chapter_id: "11" },
  { id: 6, title: "alien", chapter_id: "11" },
  { id: 7, title: "Saturn", chapter_id: "11" },
  { id: 8, title: "Mars:/", chapter_id: "21" },
  { id: 9, title: "damn", chapter_id: "3" },
  { id: 10, title: "test", chapter_id: "11" },
  { id: 11, title: "ramda heeeelp", chapter_id: "31" },
  { id: 12, title: "hello?", chapter_id: "21" }
]

И в результате я хочу получить этот объект:

{
  "3": [
    {
      "id": "9",
      "title": "damn"
    }
  ],
  "11": [
    {
      "id": "5",
      "title": "From Earth"
    },
    {
      "id": "6",
      "title": "alien"
    },
    {
      "id": "7",
      "title": "Saturn"
    },
    {
      "id": "10",
      "title": "test"
    }
  ],
  "14": [
    {
      "id": "4",
      "title": "huh!?"
    }
  ],
  "21": [
    {
      "id": "2",
      "title": "new title"
    },
    {
      "id": "8",
      "title": "Mars:/"
    },
    {
      "id": "12",
      "title": "hello?"
    }
  ],
  "31": [
    {
      "id": "11",
      "title": "ramda heeeelp"
    }
  ],
  "33": [
    {
      "id": "3",
      "title": "..."
    }
  ],
  "4321": [
    {
      "id": "1",
      "title": "hello world"
    }
  ]
}

Как я боролся с этим:

let object = {};

map(({ chapter_id }) => {
  const composed = compose(
    map(evolve({ id: toString })), //here id is converted to a string
    filter(c => c.chapter_id === chapter_id),
  );
  object[chapter_id] = composed(stuff)
}, stuff);

Мой результат:

{
  "3": [
    {
      "id": "9",
      "title": "damn",
      "chapter_id": "3" //Dissoc this
    }
  ],
  "11": [
    {
      "id": "5",
      "title": "From Earth",
      "chapter_id": "11" //dissoc this
    },
    {
      "id": "6",
      "title": "alien",
      "chapter_id": "11"  //and this
    },
    {
      "id": "7",
      "title": "Saturn",
      "chapter_id": "11" //and this
    },
    {
      "id": "10",
      "title": "test",
      "chapter_id": "11" //and this
    }
  ],
  "14": [
    {
      "id": "4",
      "title": "huh!?",
      "chapter_id": "14" //and this
    }
  ],
  "21": [
    {
      "id": "2",
      "title": "new title",
      "chapter_id": "21" //and this
    },
    {
      "id": "8",
      "title": "Mars:/",
      "chapter_id": "21" //and this
    },
    {
      "id": "12",
      "title": "hello?",
      "chapter_id": "21" //and this
    }
  ],
  "31": [
    {
      "id": "11",
      "title": "ramda heeeelp",
      "chapter_id": "31" //and this!!!!!!
    }
  ],
  "33": [
    {
      "id": "3",
      "title": "...",
      "chapter_id": "33" //and this..
    }
  ],
  "4321": [
    {
      "id": "1",
      "title": "hello world",
      "chapter_id": "4321" //and this:(
    }
  ]
}

Это работает, но я не могу отделить "chapter_id" от каждого объекта, кто-нибудь знает, как решить эту проблему? : Δ

Ответы [ 3 ]

3 голосов
/ 03 ноября 2019

С Рамдой вы можете группировать по key, а затем сопоставлять группы и отделять key от всех объектов:

const { pipe, groupBy, prop, map, dissoc } = R;

const fn = key => pipe(
  groupBy(prop(key)), // group by the key
  map(map(dissoc(key))) // remove the key from all objects in all groups
);

const stuff = [{"id":1,"title":"hello world","chapter_id":"4321"},{"id":2,"title":"new title","chapter_id":"21"},{"id":3,"title":"...","chapter_id":"33"},{"id":4,"title":"huh!?","chapter_id":"14"},{"id":5,"title":"From Earth","chapter_id":"11"},{"id":6,"title":"alien","chapter_id":"11"},{"id":7,"title":"Saturn","chapter_id":"11"},{"id":8,"title":"Mars:/","chapter_id":"21"},{"id":9,"title":"damn","chapter_id":"3"},{"id":10,"title":"test","chapter_id":"11"},{"id":11,"title":"ramda heeeelp","chapter_id":"31"},{"id":12,"title":"hello?","chapter_id":"21"}];

const result = fn('chapter_id')(stuff);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
2 голосов
/ 03 ноября 2019

Как отмечает Ори Дрори, это вероятный метод Рамды:

const transform = pipe (
  groupBy(prop('chapter_id')),
  map(map(dissoc('chapter_id'))),
)

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

const transform = pipe (
  groupBy(prop('chapter_id')),
  map(map(dissoc('chapter_id'))),
  toPairs,
  sortBy(pipe(head, Number)),
  fromPairs
)

const stuff = [{id: 1, title: "hello world", chapter_id: "4321"}, {id: 2, title: "new title", chapter_id: "21"}, {id: 3, title: "...", chapter_id: "33"}, {id: 4, title: "huh!?", chapter_id: "14"}, {id: 5, title: "From Earth", chapter_id: "11"}, {id: 6, title: "alien", chapter_id: "11"}, {id: 7, title: "Saturn", chapter_id: "11"}, {id: 8, title: "Mars: /", chapter_id: "21"}, {id: 9, title: "damn", chapter_id: "3"}, {id: 10, title: "test", chapter_id: "11"}, {id: 11, title: "ramda heeeelp", chapter_id: "31"}, {id: 12, title: "hello?", chapter_id: "21"}]

console.log (
  transform (stuff)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {pipe, groupBy, prop, map, dissoc, toPairs, sortBy, head, fromPairs} = R </script>

Эта строка сортировки может быть записана разными способами. Возможно

sort(lift(subtract)(head, head)),

или просто

sort(([a], [b]) => a - b),

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

const sortByKeys = (fn) => pipe(toPairs, sortBy(fn), fromPairs)

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

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

Прежде всего, конечная задача не описана должным образом :) Что вы действительно хотите (основываясь на результате , который я хочу получить ), это нормализовать (или реструктурировать) массив объектовв объект, который имеет chapter_id в качестве ключа, а значение представляет собой массив связанных записей массива stuff с этим chapter_id

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

reduce((acc, {chapter_id, ...rest}) => {
  const isInitialized = !!acc[chapter_id];
  if (isInitialized) {
    acc[chapter_id].push(rest); 
  } else {
    acc[chapter_id] = [rest];
  }
  return acc;
}, {}, stuff);
...