Fermer

juillet 19, 2024

Regroupement de tableaux en JavaScript

Regroupement de tableaux en JavaScript


La possibilité de combiner des données en groupes permet aux développeurs de calculer des ensembles de données d’ordre supérieur, comme regrouper les employés par service. Cet article couvre Object.groupBy et Map.groupBy en JavaScript.

Le regroupement de tableaux est une tâche que vous avez probablement implémentée en JavaScript. Si vous utilisez SQL, cela revient à faire un GROUP BY. Étant donné un ensemble de données, nous pouvons composer un ensemble de données de niveau supérieur en plaçant des données similaires dans un groupe et en identifiant chaque groupe par un identifiant donné.

je vais plonger dans le nouveau Regroupement de tableaux fonctions publiées cette année (2024), à savoir, Object.groupBy et Map.groupBy.

La prise en charge de TypeScript pour ces API est disponible sur TypeScript 5.4 pour mes fans de TypeScript. Cependant, vous devrez configurer votre tsconfig.json cibler ESNext. Lorsqu’ils sont disponibles dans ES2024, vous pouvez définir la cible sur ES2024 ou plus.

Regroupement de tableaux avant 2024

Le regroupement de tableaux en JavaScript n’est pas un concept nouveau. Nous l’avons mis en œuvre de diverses manières dans le passé. Cela pourrait être fait avec un for ou foreach boucle, Array.prototype.reduceou la groupBy fonctionner dans soulignement.js ou lodash.

Étant donné une liste d’employés, voici comment nous regrouperions les données en utilisant reduce():

interface Employee {
  name: string;
  department: string;
  age: number;
  manager?: Employee;
  joined: Date
}

const ceo = {
    name: "John Doe",
    department: "engineering",
    age: 47,
    joined: new Date("10-04-2020")
}

const cfo = {
    name: "Anna Maria",
    department: "finance",
    age: 45,
    joined: new Date("10-05-2020")
  }

 const employees: Employee[] = [
  ceo,
  {
    name: "Pop Jones Jr.",
    department: "finance",
    age: 30,
    manager: cfo,
    joined: new Date("10-04-2021")
  },
  {
    name: "Sarah Clara",
    department: "engineering",
    age: 32,
    manager: ceo,
    joined: new Date("10-05-2021")
  },
  cfo,
  {
    name: "Funmi Kola",
    department: "engineering",
    age: 20,
    manager: ceo,
    joined: new Date("10-05-2022")
  },
  {
    name: "Julius Maria",
    department: "sales",
    age: 27,
    manager: cfo,
    joined: new Date("10-05-2022")
  }
 ]

const groupByDepartment = employees.reduce<Record<string, Employee[]>>((acc, employee) => {
  const department = employee.department;
  if (acc[department] === undefined) {
    acc[department] = [];
  }

  acc[department].push(employee);
  return acc;
}, {});

console.log(groupByDepartment);

La sortie pour groupByDepartment devrait être:

{
    "engineering": [
        {
            "name": "John Doe",
            "department": "engineering",
            "age": 47,
            "joined": "2020-10-03T22:00:00.000Z"
        },
        {
            "name": "Sarah Clara",
            "department": "engineering",
            "age": 32,
            "manager": {
                "name": "John Doe",
                "department": "engineering",
                "age": 47,
                "joined": "2020-10-03T22:00:00.000Z"
            },
            "joined": "2021-10-04T22:00:00.000Z"
        },
        {
            "name": "Funmi Kola",
            "department": "engineering",
            "age": 20,
            "manager": {
                "name": "John Doe",
                "department": "engineering",
                "age": 47,
                "joined": "2020-10-03T22:00:00.000Z"
            },
            "joined": "2022-10-04T22:00:00.000Z"
        }
    ],
    "finance": [
        {
            "name": "Pop Jones Jr.",
            "department": "finance",
            "age": 30,
            "manager": {
                "name": "Anna Maria",
                "department": "finance",
                "age": 45,
                "joined": "2020-10-04T22:00:00.000Z"
            },
            "joined": "2021-10-03T22:00:00.000Z"
        },
        {
            "name": "Anna Maria",
            "department": "finance",
            "age": 45,
            "joined": "2020-10-04T22:00:00.000Z"
        }
    ],
    "sales": [
        {
            "name": "Julius Maria",
            "department": "sales",
            "age": 27,
            "manager": {
                "name": "Anna Maria",
                "department": "finance",
                "age": 45,
                "joined": "2020-10-04T22:00:00.000Z"
            },
            "joined": "2022-10-04T22:00:00.000Z"
        }
    ]
}

Regroupement avec Object.groupBy

Le Object.groupBy La fonction est utilisée pour regrouper selon une valeur de chaîne donnée. Cela signifie : étant donné un itérable, regroupez ses éléments en fonction de la valeur renvoyée par la fonction de rappel fournie. La valeur renvoyée par le rappel doit être quelque chose qui peut être converti en chaîne ou en symbole.

Object.groupBy renvoie un objet prototype nul qui a des propriétés distinctes pour chaque groupe, contenant des tableaux avec les éléments du groupe. L’utilisation d’un objet prototype nul permet une déstructuration ergonomique et évite les collisions accidentelles avec les propriétés globales de l’objet.

En utilisant le même ensemble de données, nous pouvons regrouper les employés par service en utilisant Object.groupBy:

const groupByDepartment = Object.groupBy(employees, ({department}) => department)

Cela nous donne le même résultat que reduce méthode mais avec moins de code. La sortie pour groupByDepartment devrait être:

{
    "engineering": [
        {
            "name": "John Doe",
            "department": "engineering",
            "age": 47,
            "joined": "2020-10-03T22:00:00.000Z"
        },
        {
            "name": "Sarah Clara",
            "department": "engineering",
            "age": 32,
            "manager": {
                "name": "John Doe",
                "department": "engineering",
                "age": 47,
                "joined": "2020-10-03T22:00:00.000Z"
            },
            "joined": "2021-10-04T22:00:00.000Z"
        },
        {
            "name": "Funmi Kola",
            "department": "engineering",
            "age": 20,
            "manager": {
                "name": "John Doe",
                "department": "engineering",
                "age": 47,
                "joined": "2020-10-03T22:00:00.000Z"
            },
            "joined": "2022-10-04T22:00:00.000Z"
        }
    ],
    "finance": [
        {
            "name": "Pop Jones Jr.",
            "department": "finance",
            "age": 30,
            "manager": {
                "name": "Anna Maria",
                "department": "finance",
                "age": 45,
                "joined": "2020-10-04T22:00:00.000Z"
            },
            "joined": "2021-10-03T22:00:00.000Z"
        },
        {
            "name": "Anna Maria",
            "department": "finance",
            "age": 45,
            "joined": "2020-10-04T22:00:00.000Z"
        }
    ],
    "sales": [
        {
            "name": "Julius Maria",
            "department": "sales",
            "age": 27,
            "manager": {
                "name": "Anna Maria",
                "department": "finance",
                "age": 45,
                "joined": "2020-10-04T22:00:00.000Z"
            },
            "joined": "2022-10-04T22:00:00.000Z"
        }
    ]
}

Regroupement avec Map.groupBy

Map.groupBy est similaire à Object.groupBy, sauf qu’il renvoie une Map et que l’itérable donné peut être regroupé en utilisant n’importe quelle valeur arbitraire. Dans ce cas, l’ensemble de données peut être regroupé à l’aide d’un objet.

En regardant l’ensemble de données, nous avons défini un manager biens de certains salariés et lui a attribué le ceo ou cfo objet. Nous pouvons regrouper les employés selon leur managerqui ressemblerait à ceci :

const managerWithTeammates = Map.groupBy(employees, ({manager}) => manager)

La sortie pour managerWithTeammates devrait ressembler à :

Map (3) 
{undefined => [{
  "name": "John Doe",
  "department": "engineering",
  "age": 47,
  "joined": "2020-10-03T22:00:00.000Z"
}, {
  "name": "Anna Maria",
  "department": "finance",
  "age": 45,
  "joined": "2020-10-04T22:00:00.000Z"
}], 
{
  "name": "Anna Maria",
  "department": "finance",
  "age": 45,
  "joined": "2020-10-04T22:00:00.000Z"
} => [{
  "name": "Pop Jones Jr.",
  "department": "finance",
  "age": 30,
  "manager": {
    "name": "Anna Maria",
    "department": "finance",
    "age": 45,
    "joined": "2020-10-04T22:00:00.000Z"
  },
  "joined": "2021-10-03T22:00:00.000Z"
}, {
  "name": "Julius Maria",
  "department": "sales",
  "age": 27,
  "manager": {
    "name": "Anna Maria",
    "department": "finance",
    "age": 45,
    "joined": "2020-10-04T22:00:00.000Z"
  },
  "joined": "2022-10-04T22:00:00.000Z"
}], 
{
  "name": "John Doe",
  "department": "engineering",
  "age": 47,
  "joined": "2020-10-03T22:00:00.000Z"
} => [{
  "name": "Sarah Clara",
  "department": "engineering",
  "age": 32,
  "manager": {
    "name": "John Doe",
    "department": "engineering",
    "age": 47,
    "joined": "2020-10-03T22:00:00.000Z"
  },
  "joined": "2021-10-04T22:00:00.000Z"
}, {
  "name": "Funmi Kola",
  "department": "engineering",
  "age": 20,
  "manager": {
    "name": "John Doe",
    "department": "engineering",
    "age": 47,
    "joined": "2020-10-03T22:00:00.000Z"
  },
  "joined": "2022-10-04T22:00:00.000Z"
}]} 

Avec cet exemple, nous avons trois groupes :

  1. Le PDG et le CFO qui n’ont pas de manager, avec undefined comme clé d’objet Map.
  2. La directrice financière, Anna Maria, qui a deux employés sous ses ordres. Cela utilise le cfo objet comme clé d’objet Map.
  3. Le PDG, John Doe, qui a deux employés sous ses ordres. Cela utilise le ceo objet comme clé d’objet Map.

Conclusion

N’est-ce pas étonnant les nouvelles API qui arrivent sur JavaScript ? Le Object.groupBy et Map.groupBy les fonctions facilitent le regroupement des données dans un tableau ou un itérable, et elles sont plus ergonomiques que les traditionnelles reduce méthode. Ils réduisent également la taille de votre bundle en ne nécessitant pas de bibliothèque externe comme lodash ou underscore.js.

Pour récapituler, utilisez le Map.groupBy fonctionnent principalement lors du regroupement d’éléments associés à un objet arbitraire, en particulier lorsque cet objet peut changer au fil du temps. Si l’objet est invariant, vous pouvez le représenter à l’aide d’une chaîne et regrouper les éléments avec Object.groupBy(). Si vous utilisez TypeScript, définissez la cible sur ESNext (ou ES2024 quand il sera disponible dans le futur).

Vous trouverez un terrain de jeu avec le code utilisé dans ce billet de blog en utilisant ceci lien.

Si vous avez des questions ou des suggestions, n’hésitez pas à laisser un commentaire. Vous pouvez également me joindre au Twitter. Merci d’avoir lu. 😎






Source link