LINQ SingleOrDefault() equivalent

43,233

Solution 1

You can always use Array.prototype.filter in this way:

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.

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

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

into

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

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

Solution 2

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

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].

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.

Solution 3

If reuse is not necessary, you could implement a singleOrDefault by applying a simple reduce function:

In this case the reducer function 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.

For example:

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

Related videos on Youtube

howardlo
Author by

howardlo

Updated on May 07, 2021

Comments

  • howardlo
    howardlo almost 3 years

    In Typescript, I use this pattern often:

    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:

    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?

  • howardlo
    howardlo over 8 years
    I use the additional [0] notation if I know that the collection would always yield a single result. And yes, the behavior for SingleOrDefault would throw an error if the collection yields more than one. Typescript has been a game changer for us and I'm looking forward for more C# like features to find it's way there. Thanks for your response.