केवल जावास्क्रिप्ट में LINQ SelectMany () के बराबर कैसे करें


93

दुर्भाग्य से, मेरे पास JQuery या अंडरस्कोर नहीं है, बस शुद्ध जावास्क्रिप्ट (IE9 संगत) है।

मैं LINQ कार्यक्षमता से SelectMany () के बराबर चाहता हूं।

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

क्या इसे मै कर सकता हूँ?

संपादित करें:

जवाब के लिए धन्यवाद, मुझे यह काम मिल गया:

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

5
यह दुर्भाग्यपूर्ण नहीं है। शुद्ध जावास्क्रिप्ट अद्भुत है। संदर्भ के बिना, यह समझना बहुत कठिन है कि आप यहां क्या हासिल करने की कोशिश कर रहे हैं।
— स्टर्लिंग आर्चर

3
@SterlingArcher, देखें कि उत्तर कितना विशिष्ट निकला। बहुत अधिक संभावित उत्तर नहीं थे और सबसे अच्छा उत्तर संक्षिप्त और संक्षिप्त था।
— टोडरमो

जवाबों:


128

एक सरल चयन के लिए आप ऐरे के कम फ़ंक्शन का उपयोग कर सकते हैं।
आओ हम कहते हैं कि आपके पास संख्याओं का सारणी है:

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]

संपादित करें:
चूंकि es6 फ्लैटपाइप को ऐरे प्रोटोटाइप में जोड़ा गया है। SelectManyका पर्याय है flatMap।
विधि पहले मैपिंग फ़ंक्शन का उपयोग करके प्रत्येक तत्व को मैप करती है, फिर परिणाम को एक नए सरणी में समतल करती है। टाइपस्क्रिप्ट में इसका सरलीकृत हस्ताक्षर है:

function flatMap<A, B>(f: (value: A) => B[]): B[]

कार्य को प्राप्त करने के लिए हमें बस प्रत्येक तत्व को फोन करने के लिए फ्लैट-मैप करना होगा

arr.flatMap(a => a.phoneNumbers);

11
उस आखिरी को भी लिखा जा सकता हैarr.reduce(function(a, b){ return a.concat(b.phoneNumbers); }, [])
— तिमवी

आपको .map () या .concat () का उपयोग करने की आवश्यकता नहीं होनी चाहिए। नीचे मेरा जवाब देखें।
— वेस्लेएसी

क्या यह मूल सरणी में परिवर्तन नहीं करता है?
— इवान

अब कम महत्वपूर्ण है, लेकिन flatMapएक IE9 संगत समाधान के लिए ओपी के अनुरोध को पूरा नहीं करता है - के लिए ब्राउज़र कॉम्पिटिटरflatmap ।
— रफिन

1
कम () खाली सरणी पर विफल रहता है, इसलिए आपको एक प्रारंभिक मूल्य जोड़ना होगा। देखें stackoverflow.com/questions/23359173/…
— हैलो

26

एक सरल विकल्प के रूप में Array.prototype.flatMap () या 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)


3
सरल और संक्षिप्त। अब तक का सबसे अच्छा जवाब।
— Ste Brown

12/4/2019 तक एमडीएन के अनुसार ऐज में फ्लैट () उपलब्ध नहीं है।
— पेटीएम

लेकिन नया एज (क्रोमियम पर आधारित) इसका समर्थन करेगा।
— नेकिप सनमाज़

2
ऐसा लगता है कि Array.prototype.flatMap () भी एक चीज है, इसलिए आपका उदाहरण सरल किया जा सकता हैconst result = data.flatMap(a => a.details)
— काइल

12

थोड़ी देर बाद उन लोगों के लिए, जावास्क्रिप्ट को समझना लेकिन फिर भी टाइपस्क्रिप्ट में एक सरल टाइप की गई चयन विधि:

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>());
}

8

सरणी को समतल करने के लिए कॉन्कैट विधि का उपयोग करने में सगी सही है। लेकिन इस उदाहरण के समान कुछ पाने के लिए, आपको चयनित भाग 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,[])

मैं '; एक बेला बनाने जा रहा हूँ; मैं आपके डेटा को json के रूप में उपयोग कर सकता हूं। अपने उत्तर को कोड की एक पंक्ति तक समतल करने का प्रयास करेंगे। "कैसे सपाट वस्तु पदानुक्रम के बारे में एक जवाब समतल करने के लिए" योग्य
— toddmo

अपने डेटा का उपयोग करने के लिए स्वतंत्र महसूस करें ... मैंने मानचित्र फ़ंक्शन को संक्षेप में सार किया ताकि आप हर बार एक नया फ़ंक्शन लिखने के बिना किसी भी संपत्ति के नाम का चयन कर सकें। बस के arrसाथ peopleऔर "pets"साथ बदलें"PhoneNumbers"
— Fabio Beltramini

चपटे संस्करण के साथ मेरे प्रश्न को संपादित किया और अपना उत्तर दिया। धन्यवाद।
— टोड्डो

1
सहायक कार्य साफ-सफाई करते हैं, लेकिन ईएस 6 के साथ आप बस ऐसा कर सकते हैं petOwners.map(owner => owner.Pets).reduce((a, b) => a.concat(b), []);:। या, और भी सरल petOwners.reduce((a, b) => a.concat(b.Pets), []);।
— एरिक

3
// 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"]}]

चलो शुरू करते हैं

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

=> [1, 2, 4, "असदा"]

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", "वी"]

नोट: कम फ़ंक्शन में गहन मान के रूप में मान्य सरणी (गैर नल) का उपयोग करें


3

यह कोशिश करो (es6 के साथ):

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

उदाहरण सरणी:

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

का उपयोग कर:

juices.SelectMany(x=>x.data)

3

मैं यह करूँगा (परहेज .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]

यदि आप .reduce () का उपयोग नहीं करना चाहते हैं:

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

यदि आप .forEach () का उपयोग करना चाहते हैं:

function SelectMany(array, arr = []) {
    array.forEach(e => {
        if (e && e.length)
            arr = SelectMany(e, arr);
        else
            arr.push(e);
    });

    return arr;
}

2
मुझे लगता है कि यह हास्यास्पद है कि मैंने 4 साल पहले यह पूछा था, और आपके उत्तर के लिए स्टैक ओवरफ्लो अधिसूचना पॉप अप हुई थी, और मैं इस समय जो कर रहा हूं वह जेएस सरणियों से जूझ रहा है। बहुत अच्छा!
— टोडरमो

मुझे खुशी है कि किसी ने इसे देखा! मुझे आश्चर्य हुआ कि मैंने जो कुछ लिखा था वह पहले से सूचीबद्ध नहीं था, यह देखते हुए कि धागा कितने समय से चल रहा है और कितने उत्तर दिए गए हैं।
— 20

@toddmo इसके लायक क्या है, यदि आप अभी js सरण पर काम कर रहे हैं, तो आप हाल ही में यहां जोड़े गए समाधान में दिलचस्पी ले सकते हैं: stackoverflow.com/questions/1960473/… ।
— वेस्लेएसी

2

यहाँ आप टाइप, किसी एक्सटेंशन पर प्रयोग करने योग्य टाइपस्क्रिप्ट में joel-harkes के उत्तर को फिर से लिखे गए संस्करण पर जाते हैं। तो आप सचमुच इसे पसंद कर सकते हैं somearray.selectMany(c=>c.someprop)। ट्रांस-ढेर, यह जावास्क्रिप्ट है।

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 { };

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.