如何在javascript中完成等效的LINQ SelectMany()

tod*_*dmo 68 javascript c#

不幸的是,我没有JQuery或Underscore,只是纯粹的javascript(IE9兼容).

我想从LINQ功能中获得相当于SelectMany()的功能.

// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);
Run Code Online (Sandbox Code Playgroud)

我可以做吗?

编辑:

感谢答案,我得到了这个工作:

var petOwners = 
[
    {
        Name: "Higa, Sidney", Pets: ["Scruffy", "Sam"]
    },
    {
        Name: "Ashkenazi, Ronen", Pets: ["Walker", "Sugar"]
    },
    {
        Name: "Price, Vernette", Pets: ["Scratches", "Diesel"]
    },
];

function property(key){return function(x){return x[key];}}
function flatten(a,b){return a.concat(b);}

var allPets = petOwners.map(property("Pets")).reduce(flatten,[]);

console.log(petOwners[0].Pets[0]);
console.log(allPets.length); // 6

var allPets2 = petOwners.map(function(p){ return p.Pets; }).reduce(function(a, b){ return a.concat(b); },[]); // all in one line

console.log(allPets2.length); // 6
Run Code Online (Sandbox Code Playgroud)

Sag*_*agi 93

对于简单的选择,您可以使用Array的reduce函数.
假设您有一组数字数组:

var arr = [[1,2],[3, 4]];
arr.reduce(function(a, b){ return a.concat(b); });
=>  [1,2,3,4]

var arr = [{ name: "name1", phoneNumbers : [5551111, 5552222]},{ name: "name2",phoneNumbers : [5553333] }];
arr.map(function(p){ return p.phoneNumbers; })
   .reduce(function(a, b){ return a.concat(b); })
=>  [5551111, 5552222, 5553333]
Run Code Online (Sandbox Code Playgroud)

  • 最后一个也可以写成`arr.reduce(function(a,b){return a.concat(b.phoneNumbers);},[])` (10认同)
  • reduce() 在空数组上失败,因此您必须添加一个初始值。请参阅/sf/ask/1635142141/ (2认同)

Joe*_*kes 9

稍后,请理解javascript,但仍希望在Typescript中使用简单的Typed SelectMany方法:

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>());
}
Run Code Online (Sandbox Code Playgroud)


Nec*_*maz 9

作为一个更简单的选项,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.map(a => a.details).flat(1);
console.log(result)
Run Code Online (Sandbox Code Playgroud)

  • 看起来 [Array.prototype.flatMap()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap) 也是一件事,所以你的例子可以简化为 `const result = data.flatMap(a =&gt; a.details)` (3认同)
  • 简单明了。迄今为止最好的答案。 (2认同)

Fab*_*ini 8

Sagi在使用concat方法展平数组时是正确的.但是为了得到类似于这个例子的东西,你还需要一个选择部分的地图 https://msdn.microsoft.com/library/bb534336(v=vs.100).aspx

/* arr is something like this from the example PetOwner[] petOwners = 
                    { new PetOwner { Name="Higa, Sidney", 
                          Pets = new List<string>{ "Scruffy", "Sam" } },
                      new PetOwner { Name="Ashkenazi, Ronen", 
                          Pets = new List<string>{ "Walker", "Sugar" } },
                      new PetOwner { Name="Price, Vernette", 
                          Pets = new List<string>{ "Scratches", "Diesel" } } }; */

function property(key){return function(x){return x[key];}}
function flatten(a,b){return a.concat(b);}

arr.map(property("pets")).reduce(flatten,[])
Run Code Online (Sandbox Code Playgroud)

  • 辅助函数会清理一些东西,但是在 ES6 中你可以这样做:`petOwners.map(owner =&gt; owner.Pets).reduce((a, b) =&gt; a.concat(b), []); `. 或者,甚至更简单,`petOwners.reduce((a, b) =&gt; a.concat(b.Pets), []);`。 (2认同)