在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 );
我正在考虑创建类似于LINQ Material Design guidelines方法的JavaScript扩展,如果它不在数组中,则返回null
:
var item = vegetable.singleOrDefault( xvegetable => {
return xvegetable.id == id});
我的问题是,如果没有创建自定义界面,是否还有其他方法可以实现这一目标?
答案 0 :(得分:27)
您可以始终以这种方式使用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
修改的
我的回答适用于FirstOrDefault
,而不是SingleOrDefault
SingleOrDefault
检查是否只有一个匹配,在我的情况下(以及在您的代码中),您返回第一个匹配而不检查另一个匹配。
BTW,如果你想要实现SingleOrDefault
,那么你需要改变它:
var item = collection.length < 1 ? null : collection[0];
进入
if(collection.length > 1)
throw "Not single result....";
return collection.length === 0 ? null : collection[0];
答案 1 :(得分:19)
如果你想在数组中找到一个项目,我建议你使用ES6 find method,如下:
select u.*, b.numbuyer, s.numseller
from users u left join
(select buyer, count(*) as numbuyer
from transactions
group by buyer
) b
on b.buyer = u.user_id left join
(select seller, count(*) as numseller
from transactions
group by seller
) s
on s.buyer = u.user_id;
它更快更容易阅读,因为您不需要写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#collection[0]
找到多个元素,它会引发异常。在这里,您尝试进行SingleOrDefault
扩展。
答案 2 :(得分:0)
现在,有一个库可以在打字稿中提供强类型的可查询集合。
该库称为ts-generic-collections。
GitHub上的源代码:
https://github.com/VeritasSoftware/ts-generic-collections
使用此库,您可以编写如下所示的查询:
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();
答案 3 :(得分:0)
如果不需要重用,则可以通过应用简单的reduce函数来实现singleOrDefault
:
在这种情况下,仅当数组不为空时才计算 reducer 函数。当长度大于1时抛出该异常,否则返回唯一的元素。当数组为空时,将返回reduce函数的默认值参数:在这种情况下为null
。
例如:
[].reduce(function(acc, cur, idx, src) {
if (src.length > 1) {
throw 'More than one found';
}
return src[0];
}, null);
答案 4 :(得分:0)
你可以使用reduce:
// add as prototype
Array.prototype.singleOrDefault = function(filter) {
return this.reduce(function(current, next) {
if (filter && !filter(next))
return current;
if (current)
throw 'The input sequence contains more than one element';
return next;
}, null);
}
// test cases
const input = [1, 2, 3, 4, 5, 6, 1];
console.log("input: " + input);
console.log("Test 1 (=4 => found): " + input.singleOrDefault(m => m == 4));
try {
input.singleOrDefault(m => m == 1);
}
catch(err) {
console.error("Test 2 (=1 => error): " + err);
}
try {
input.singleOrDefault();
}
catch(err) {
console.error("Test 3 (without filter => error): " + err);
}
console.log("Test 4 (one item + without filter => found): " + [10].singleOrDefault());