web-dev-qa-db-fra.com

Équivalent LINQ SingleOrDefault ()

Dans TypeScript, j'utilise souvent ce modèle:

class Vegetable {
    constructor(public id: number, public name: string) {
    }
}

var vegetable_array = new Array<Vegetable>();
vegetable_array.Push(new Vegetable(1, "Carrot"));
vegetable_array.Push(new Vegetable(2, "Bean"));
vegetable_array.Push(new Vegetable(3, "Peas"));

var id = 1;
var collection = vegetable_array.filter( xvegetable => {
    return xvegetable.id == id;
});
var item = collection.length < 1 ? null : collection[0];

console.info( item.name );

Je pense à créer une extension JavaScript similaire à la méthode LINQ SingleOrDefault où elle renvoie null si elle n'est pas dans le tableau:

var item = vegetable.singleOrDefault( xvegetable => {
    return xvegetable.id == id});

Ma question est de savoir s'il existe un autre moyen d'y parvenir sans créer une interface personnalisée?

28
howardlo

Vous pouvez toujours utiliser Array.prototype.filter de cette manière:

var arr = [1,2,3];
var notFoundItem = arr.filter(id => id === 4)[0]; // will return undefined
var foundItem = arr.filter(id => id === 3)[0]; // will return 3

Modifier
Ma réponse s'applique à FirstOrDefault et non à SingleOrDefault.
SingleOrDefault vérifie s'il n'y a qu'une seule correspondance et dans mon cas (et dans votre code) vous retournez la première correspondance sans rechercher une autre correspondance.

BTW, si vous vouliez atteindre SingleOrDefault alors vous auriez besoin de changer ceci:

var item = collection.length < 1 ? null : collection[0];

dans

if(collection.length > 1)
   throw "Not single result....";

return collection.length === 0 ? null : collection[0];
30
Amir Popovich

Si vous voulez trouver un élément dans le tableau, je vous suggère d'utiliser méthode de recherche ES6 , comme ceci:

const inventory = [
    { name: 'apples', quantity: 2 },
    { name: 'bananas', quantity: 0 },
    { name: 'cherries', quantity: 5 }
];

const result = inventory.find(fruit => fruit.name === 'cherries');

console.log(result) // { name: 'cherries', quantity: 5 }

C'est plus rapide et plus facile à lire, car vous n'avez pas besoin d'écrire collection[0].

Soit dit en passant, SingleOrDefault de C # lève une exception s'il a trouvé plusieurs éléments. Ici, vous essayez de créer une extension FirstOrDefault.

22
Andzej Maciusovic

Si la réutilisation n'est pas nécessaire, vous pouvez implémenter un singleOrDefault en appliquant une simple fonction réduire :

Dans ce cas, la fonction de réduction n'est calculée que lorsque le tableau n'est pas vide. Il lance lorsque la longueur est supérieure à 1, sinon il renvoie le seul élément. Lorsque le tableau est vide, le paramètre de valeur par défaut de la fonction de réduction est renvoyé: dans ce cas null.

Par exemple:

[].reduce(function(acc, cur, idx, src) {
  if (src.length > 1) {
    throw 'More than one found';
  }
  return src[0];
}, null);
1
Philip Bijker

Maintenant, il existe une bibliothèque qui fournit des collections fortement typées et interrogeables en TypeScript.

La bibliothèque s'appelle ts-generic-collections.

Code source sur GitHub:

https://github.com/VeritasSoftware/ts-generic-collections

Avec cette bibliothèque, vous pouvez écrire des requêtes comme indiqué ci-dessous:

    let owners = new List<Owner>();

    let owner = new Owner();
    owner.id = 1;
    owner.name = "John Doe";
    owners.add(owner);

    owner = new Owner();
    owner.id = 2;
    owner.name = "Jane Doe";
    owners.add(owner);    

    let pets = new List<Pet>();

    let pet = new Pet();
    pet.ownerId = 2;
    pet.name = "Sam";
    pet.sex = Sex.M;

    pets.add(pet);

    pet = new Pet();
    pet.ownerId = 1;
    pet.name = "Jenny";
    pet.sex = Sex.F;

    pets.add(pet);

    //query to get owners by their pet's gender/sex
    let ownersByPetSex = owners.join(pets, owner => owner.id, pet => pet.ownerId, (x, y) => new OwnerPet(x,y))
                               .groupBy(x => [x.pet.sex])
                               .select(x =>  new OwnersByPetSex(x.groups[0], x.list.select(x => x.owner)));

    expect(ownersByPetSex.toArray().length === 2).toBeTruthy();

    expect(ownersByPetSex.toArray()[0].sex == Sex.F).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.length === 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.toArray()[0].name == "John Doe").toBeTruthy();

    expect(ownersByPetSex.toArray()[1].sex == Sex.M).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.length == 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.toArray()[0].name == "Jane Doe").toBeTruthy(); 
0
John