How to do equivalent of LINQ SelectMany() just in javascript

后端 未结 9 1392
隐瞒了意图╮
隐瞒了意图╮ 2020-12-13 16:54

Unfortunately, I don\'t have JQuery or Underscore, just pure javascript (IE9 compatible).

I\'m wanting the equivalent of SelectMany() from LINQ functionality.

<
相关标签:
9条回答
  • 2020-12-13 17:18

    As a simpler option Array.prototype.flatMap() or Array.prototype.flat()

    const data = [
    {id: 1, name: 'Dummy Data1', details: [{id: 1, name: 'Dummy Data1 Details'}, {id: 1, name: 'Dummy Data1 Details2'}]},
    {id: 1, name: 'Dummy Data2', details: [{id: 2, name: 'Dummy Data2 Details'}, {id: 1, name: 'Dummy Data2 Details2'}]},
    {id: 1, name: 'Dummy Data3', details: [{id: 3, name: 'Dummy Data3 Details'}, {id: 1, name: 'Dummy Data3 Details2'}]},
    ]
    
    const result = data.flatMap(a => a.details); // or data.map(a => a.details).flat(1);
    console.log(result)

    0 讨论(0)
  • 2020-12-13 17:18
    // you can save this function in a common js file of your project
    function selectMany(f){ 
        return function (acc,b) {
            return acc.concat(f(b))
        }
    }
    
    var ex1 = [{items:[1,2]},{items:[4,"asda"]}];
    var ex2 = [[1,2,3],[4,5]]
    var ex3 = []
    var ex4 = [{nodes:["1","v"]}]
    

    Let's start

    ex1.reduce(selectMany(x=>x.items),[])
    

    => [1, 2, 4, "asda"]

    ex2.reduce(selectMany(x=>x),[])
    

    => [1, 2, 3, 4, 5]

    ex3.reduce(selectMany(x=> "this will not be called" ),[])
    

    => []

    ex4.reduce(selectMany(x=> x.nodes ),[])
    

    => ["1", "v"]

    NOTE: use valid array (non null) as intitial value in the reduce function

    0 讨论(0)
  • 2020-12-13 17:18

    Here you go, a rewritten version of joel-harkes' answer in TypeScript as an extension, usable on any array. So you can literally use it like somearray.selectMany(c=>c.someprop). Trans-piled, this is javascript.

    declare global {
        interface Array<T> {
            selectMany<TIn, TOut>(selectListFn: (t: TIn) => TOut[]): TOut[];
        }
    }
    
    Array.prototype.selectMany = function <TIn, TOut>( selectListFn: (t: TIn) => TOut[]): TOut[] {
        return this.reduce((out, inx) => {
            out.push(...selectListFn(inx));
            return out;
        }, new Array<TOut>());
    }
    
    
    export { };
    
    0 讨论(0)
  • 2020-12-13 17:20

    I would do this (avoiding .concat()):

    function SelectMany(array) {
        var flatten = function(arr, e) {
            if (e && e.length)
                return e.reduce(flatten, arr);
            else 
                arr.push(e);
            return arr;
        };
    
        return array.reduce(flatten, []);
    }
    
    var nestedArray = [1,2,[3,4,[5,6,7],8],9,10];
    console.log(SelectMany(nestedArray)) //[1,2,3,4,5,6,7,8,9,10]
    

    If you don't want to use .reduce():

    function SelectMany(array, arr = []) {
        for (let item of array) {
            if (item && item.length)
                arr = SelectMany(item, arr);
            else
                arr.push(item);
        }
        return arr;
    }
    

    If you want to use .forEach():

    function SelectMany(array, arr = []) {
        array.forEach(e => {
            if (e && e.length)
                arr = SelectMany(e, arr);
            else
                arr.push(e);
        });
    
        return arr;
    }
    
    0 讨论(0)
  • 2020-12-13 17:22

    For those a while later, understanding javascript but still want a simple Typed SelectMany method in Typescript:

    function selectMany<TIn, TOut>(input: TIn[], selectListFn: (t: TIn) => TOut[]): TOut[] {
      return input.reduce((out, inx) => {
        out.push(...selectListFn(inx));
        return out;
      }, new Array<TOut>());
    }
    
    0 讨论(0)
  • 2020-12-13 17:23

    try this (with es6):

     Array.prototype.SelectMany = function (keyGetter) {
     return this.map(x=>keyGetter(x)).reduce((a, b) => a.concat(b)); 
     }
    

    example array :

     var juices=[
     {key:"apple",data:[1,2,3]},
     {key:"banana",data:[4,5,6]},
     {key:"orange",data:[7,8,9]}
     ]
    

    using :

    juices.SelectMany(x=>x.data)
    
    0 讨论(0)
提交回复
热议问题