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
LINQ SingleOrDefault() equivalent
提问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 SingleOrDefault
method where it returns null
if 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 FirstOrDefault
and not to SingleOrDefault
.SingleOrDefault
checks 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 SingleOrDefault
then 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 SingleOrDefault
throws an exception if it found more than one element. Here you're trying to make a FirstOrDefault
extension.
顺便说一句,如果 C#SingleOrDefault
找到多个元素,则会引发异常。在这里,您正在尝试进行FirstOrDefault
扩展。
回答by Philip Bijker
If reuse is not necessary, you could implement a singleOrDefault
by 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();