2
votes

Regrouper plusieurs objets en fonction du type à l'aide de lodash

Je veux regrouper un unordered-list-item ordered-list-item et un unordered-list-item ordered-list-item .

Voici la structure originale:

<script src="https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js"></script>

Maintenant, je veux regrouper tous les éléments de la liste dans un nouvel objet.

La structure attendue est donc:

var content = {
  data: {
    areas: [{
      sections: [{
        rjf: [{
            type: "unordered-list-item",
            text: "Item 1",
          },
          {
            type: "unordered-list-item",
            text: "Item 2",
          },
          {
            type: "paragraph",
            text: "This is text",
          }
        ]
      }]
    }]
  }
};

var result = content.data.areas.map((area => {
    return area.sections.map(section => {
       section.rfj = _.groupBy(section.rfj, 'type');
    });
}));

document.body.innerHTML = '<pre>' + JSON.stringify(result, null, '  ') + '</pre>';

Je voulais donc déplacer tous les éléments unordered-list-item and ordered-list-item vers le tableau d' items et le type objet suivant comme paragraph ne devrait pas être affecté.

J'ai créé une solution dans TypeScript, mais le code était trop long:

const areas = data.areas;
      const listItemTypes = ['unordered-list-item', 'ordered-list-item'];
      return areas.map(area => {
        return area.sections.map(section => {
          let lastHeadingIndex = -1;
          return section.rjf.reduce((acc, current, index) => {
            if (!current.type || !listItemTypes.includes(current.type)) {
              lastHeadingIndex = acc.length;
              return [...acc, current];
            }
            let listObject = acc.find((el, i) => i > lastHeadingIndex && i < index && el.type === 'list');
            if (!listObject) {
              listObject = {
                type: 'list',
                items: [current]
              };
              return [...acc, listObject];
            }
            listObject.items = [...listObject.items, current];
            return acc;
          }, []);
        });
      });

Comment puis-je obtenir la même fonctionnalité en utilisant lodash?

****MISE À JOUR****

J'ai essayé avec lodash, mais cela ne semble pas fonctionner.

{
  data: {
    areas: [{
      sections: [{
        rjf: [
          {
            type: "list",
            items: [{
              type: "unordered-list-item",
              text: "Item 1",
            },
            {
              type: "unordered-list-item",
              text: "Item 2",
            }]
          },
          {
            type: "paragraph",
            text: "This is text",
          }]
      }]
    }]
  }
}
{
  data: {
    areas: [{
      sections: [{
        rjf: [
          {
            type: "unordered-list-item",
            text: "Item 1",
          },
          {
            type: "unordered-list-item",
            text: "Item 2",
          },
          {
            type: "paragraph",
            text: "This is text",
          }]
      }]
    }]
  }
}


2 commentaires

Êtes-vous d'accord avec la mutation de l'entrée ou voulez-vous un nouvel objet?


Je voulais un nouvel objet


3 Réponses :


0
votes
return data.areas.map((area => {
    return area.sections.map(section => {
       return section.rfj = _.groupBy(section.rfj, 'type')
    })
})
You may need some more little tweaking on the result if you need a more specific structure, but this should do most of the work

1 commentaires

Ouais des data. au début est faux. Il doit s'agir de content.data.areas(...



0
votes

Vous pouvez simplifier votre code en quelque chose comme ça.

  • Utilisez une map imbriquée sur les areas et les sections .
  • Vous relancez les tableaux des deux map . Renvoie à la place des objets avec des sections et rjf propriété rjf (en supposant que les deux structures sont des objets avec une seule propriété)
  • Lorsque vous parcourez rjf , créez 2 tableaux: items et others
  • Regroupez chaque objet dans ces 2 tableaux selon que le tableau de types includes le type l'objet actuel.
  • Créer un tableau avec un objet list ( { type: "list", items } ) et les objets restants des others tableaux

.as-console-wrapper { max-height: 100% !important; top: 0; }
const types = ['unordered-list-item', 'ordered-list-item'],
      input = {data:{areas:[{sections:[{rjf:[{type:"unordered-list-item",text:"Item 1",},{type:"unordered-list-item",text:"Item 2",},{type:"paragraph",text:"This is text",}]}]}]}}

const areas = input.data.areas.map(a => {
  return {
    sections: a.sections.map(s => {
      const items = [], others = [];
      
      s.rjf.forEach(o =>
        types.includes(o.type) ? items.push(o) : others.push(o)
      )

      return { rjf: [{ type: "list", items }, ...others] }
    })
  }
})

console.log({ data: { areas } })


0 commentaires

0
votes

Vous pouvez utiliser une autre approche en copiant chaque niveau d'objet et mapper tous les tableaux et regrouper le dernier niveau en utilisant une fonction de regroupement.

Cette approche utilise une fonction iter qui obtient toutes les fonctions pour chaque niveau et l'objet de départ.

À la fin, il renvoie un nouvel objet avec la structure donnée et les éléments groupés.

.as-console-wrapper { max-height: 100% !important; top: 0; }
function copy(source, fn) {
    return Object.assign({}, ...Object
        .entries(source)
        .map(([k, v]) => ({ [k]: fn(v) }))
    );
}

function map(array, fn) {
    return array.map(fn);
}

function group(array) {
    var items;
    return array.reduce((r, o) => {
        if (listItemTypes.includes(o.type)) {
            if (!items) {
                items = [];
                r.push({ type: 'list', items });
            }
            items.push(o);
        } else {
            items = undefined;
            r.push(o);
        }
        return r;
    }, []);
}

function iter([fn, ...fns], object) {
    return fn ? fn(object, iter.bind(null, fns)) : object;
}    

var object = { data: { areas: [{ sections: [{ rjf: [{ type: "unordered-list-item", text: "Item 1" }, { type: "unordered-list-item", text: "Item 2" }, { type: "paragraph", text: "This is text" }] }] }] } },
    listItemTypes = ['unordered-list-item', 'ordered-list-item'],
    result = iter([copy, copy, map, copy, map, copy, group], object);

console.log(result);


0 commentaires