J'ai plusieurs éléments
, dont certains avec le même titre
. Je souhaite créer un tableau multidimensionnel avec le title
comme première clé et un numéro unique comme deuxième clé. Il est donc possible de classer les éléments
par title
.
Exemple:
$itemArray = array(); foreach ($items as $key => $item) { $itemArray[$item['title']][] = $item; }
Mon exemple fonctionne avec ceci code, mais à mon avis, c'est trop compliqué et j'espère qu'il existe une autre façon avec JavaScript.
{ 'booktitle': { '0': RowDataPacket { uid: 1, title: 'booktitle', description: 'description' } }, { '1': RowDataPacket { uid: 2, title: 'booktitle', description: 'description 2' } }, 'booktitle 2': { '0': RowDataPacket { uid: 1, title: 'booktitle 2', description: 'description' } } }
L'entrée:
[ RowDataPacket { uid: 1, title: 'booktitle', description: 'description' }, RowDataPacket { uid: 2, title: 'booktitle', description: 'description 2' }, RowDataPacket { uid: 1, title: 'booktitle 2', description: 'description' } ]
Sortie attendue (comme c'est le résultat d'une requête SQL, l'élément est un RowDataPacket):
let itemArray = {} items.forEach(item => { let title = item['title'] if (itemArray[title] == null) { itemArray[title] = {} } let index = Object.keys(itemArray[title]).length itemArray[title][index] = item }, )
C'est facile avec PHP, là ça marche comme ça:
itemArray['title1'][0] = item1 itemArray['title1'][1] = item2 itemArray['title2'][0] = item3
Merci d'avance!
3 Réponses :
Vous avez la bonne idée. Le itemArray
que vous avez créé n'est pas un tableau multidimensionnel. C'est un objet avec chaque titre
comme clé et un tableau de éléments
qui partagent le même titre
que leur valeur. Vous pourriez probablement simplifier votre forEach
comme ceci:
var items=[{uid:1,title:'booktitle',description:'description'},{uid:2,title:'booktitle',description:'description 2'},{uid:1,title:'booktitle 2',description:'description'}] let itemArray = items.reduce((acc,i) => ((acc[i.title] = acc[i.title] || []).push(i), acc) ,{}) console.log(itemArray)
Vérifiez si itemArray
a déjà le title
comme clé. Si oui, utilisez-le. Sinon, pointez-le vers un tableau vide []
. Ensuite, il suffit de push
item
actuel à cette propriété.
Avec reduction
, vous pouvez même le simplifier en:
var items = [{ uid: 1, title: 'booktitle', description: 'description' }, { uid: 2, title: 'booktitle', description: 'description 2' }, { uid: 1, title: 'booktitle 2', description: 'description' }] let itemArray = {} items.forEach(item => { itemArray[item.title] = itemArray[item.title] || []; itemArray[item.title].push(item) }) console.log(itemArray)
Vous pouvez réduire le tableau en prenant un tableau par défaut et en poussant l'élément.
var items = [{ title: 'title1' }, { title: 'title1' }, { title: 'title2' }], result = items.reduce((r, item) => { (r[item.title] = r[item.title] || []).push(item); return r; }, {}); console.log(result);
Merci :) Il fonctionne avec cette solution et semble être le plus rapide.
Résultat attendu
{'booktitle': {'0': RowDataPacket { uid: 1, title: 'booktitle', description: 'description'}}, { '1': RowDataPacket { uid: 2, title: 'booktitle', description: 'description 2'}}, 'booktitle 2': {'0': RowDataPacket { uid: 1, title: 'booktitle 2', description: 'description'}} }
C'est une mauvaise pratique. N'utilisez pas de propriétés énumérées sur les objets. Vous voyez à quel point ils sont encombrants. Contrairement à PHP, JS n'a pas de tableaux associatifs; donc utiliser des objets pour cela est le bon équivalent. Mais pour les tableaux indexés, vous devez utiliser des tableaux dans JS, pas des objets.
.as-console-wrapper{top:0;max-height:100%!important}var data = [{ uid: 1, title: 'booktitle', description: 'description' }, { uid: 2, title: 'booktitle', description: 'description 2' }, { uid: 1, title: 'booktitle 2', description: 'description' } ]; function groupBy(iterable, keyOrFn) { const fn = typeof keyOrFn === "function" ? keyOrFn : (item) => item == null ? undefined : item[keyOrFn]; var result = Object.create(null); for (const item of iterable) { const key = fn(item); if (key in result) { result[key].push(item); } else { result[key] = [item]; } } return result; } const booksByTitle = groupBy(data, "title"); console.log(booksByTitle);mais il existe également de nombreux frameworks dans JS qui offrent une méthode
groupBy
, quelque chose comme cette implémentation rapide:
.as-console-wrapper{top:0;max-height:100%!important}var data = [{ uid: 1, title: 'booktitle', description: 'description' }, { uid: 2, title: 'booktitle', description: 'description 2' }, { uid: 1, title: 'booktitle 2', description: 'description' } ]; const booksByTitle = {}; for (const item of data) { const { title } = item; if (!(title in booksByTitle)) booksByTitle[title] = []; booksByTitle[title].push(item); } console.log(booksByTitle);
Publiez votre entrée et sortie attendue :)
J'ai ajouté le résultat attendu et les données d'entrée.
@Emma Merci, mais comment utiliser .name quand le nom est aussi juste la valeur d'une autre variable?