typescript LINQ SingleOrDefault()等价

tvz2xvvm  于 2023-04-22  发布在  TypeScript
关注(0)|答案(4)|浏览(122)

在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 SingleOrDefault方法的JavaScript扩展,如果它不在数组中,则返回null

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

我的问题是,是否有另一种方法来实现这一点,而无需创建一个自定义界面?

4szc88ey

4szc88ey1#

您可以始终以这种方式使用Array.prototype.filter

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

编辑

我的答案适用于FirstOrDefault,而不是SingleOrDefault
SingleOrDefault检查是否只有一个匹配,在我的例子中(在你的代码中),你返回第一个匹配,而不检查另一个匹配。
顺便说一句,如果你想实现SingleOrDefault,那么你需要改变这一点:

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

进入

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

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

h9a6wy2h2#

如果你想在数组中找到一个元素,我建议你使用ES6 find method,像这样:

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 }

它更快,更容易阅读,因为你不需要写collection[0]
顺便说一下,如果C#的SingleOrDefault找到多个元素,它会抛出一个异常。

lf3rwulv

lf3rwulv3#

如果不需要重用,可以通过应用一个简单的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);
blmhpbnm

blmhpbnm4#

你可以使用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());

相关问题