Javascript LINQ SingleOrDefault() 等效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33065696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:34:58  来源:igfitidea点击:

LINQ SingleOrDefault() equivalent

javascriptlinqtypescripttypescript1.5

提问by howardlo

In Typescript, I use this pattern often:

在 Typescript 中,我经常使用这种模式:

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 );

I am thinking about creating a JavaScript extension similar to the LINQ SingleOrDefaultmethod where it returns nullif it's not in the array:

我正在考虑创建一个类似于 LINQSingleOrDefault方法的 JavaScript 扩展,null如果它不在数组中,它将返回:

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

My question is whether there is another way to achieve this without creating a custom interface?

我的问题是是否有另一种方法可以在不创建自定义界面的情况下实现这一目标?

回答by Amir Popovich

You can always use Array.prototype.filterin this way:

你总是可以这样使用Array.prototype.filter

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

Edit
My answer applies to FirstOrDefaultand not to SingleOrDefault.
SingleOrDefaultchecks if there is only one match and in my case (and in your code) you return the first match without checking for another match.

编辑
我的答案适用于FirstOrDefault而不适用于SingleOrDefault.
SingleOrDefault检查是否只有一个匹配项,在我的情况下(以及在您的代码中),您返回第一个匹配项而不检查另一个匹配项。

BTW,If you wanted to achieve SingleOrDefaultthen you would need to change this:

顺便说一句,如果你想实现SingleOrDefault那么你需要改变这个:

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

into

进入

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

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

回答by Andzej Maciusovic

If you want to find one item in array, I suggest you to use ES6 find method, like so:

如果您想在数组中查找一项,我建议您使用ES6 find 方法,如下所示:

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 }

It's faster and easier to read, because you don't need to write collection[0].

它更快更容易阅读,因为您不需要编写collection[0].

By the way, C#'s SingleOrDefaultthrows an exception if it found more than one element. Here you're trying to make a FirstOrDefaultextension.

顺便说一句,如果 C#SingleOrDefault找到多个元素,则会引发异常。在这里,您正在尝试进行FirstOrDefault扩展。

回答by Philip Bijker

If reuse is not necessary, you could implement a singleOrDefaultby applying a simple reducefunction:

如果不需要重用,您可以singleOrDefault通过应用一个简单的reduce函数来实现:

In this case the reducerfunction is only calculated when the array is not empty. It throws when the length is greater than 1, otherwise it returns the only element. When the array is empty, the default value parameter of the reduce function is returned: in this case null.

在这种情况下,reducer函数仅在数组不为空时计算。当长度大于 1 时抛出,否则返回唯一元素。当数组为空时,返回reduce函数的默认值参数:在这种情况下null

For example:

例如:

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

回答by John

Now, there is a library which provides strongly-typed, queryable collections in typescript.

现在,有一个库可以在打字稿中提供强类型、可查询的集合。

The library is called ts-generic-collections.

该库称为 ts-generic-collections。

Source code on GitHub:

GitHub 上的源代码:

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

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

With this library, you can write queries as shown below:

使用此库,您可以编写如下所示的查询:

    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();