मर्ज / सरणी को समतल करें


1104

मेरे पास एक जावास्क्रिप्ट सरणी है जैसे:

[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]

मैं अलग आंतरिक सरणियों को एक में विलय करने के बारे में कैसे जाऊंगा:

["$6", "$12", "$25", ...]

gist.github.com/Nishchit14/4c6a7349b3c778f7f97b912629a9f228 यह लिंक ES5 और ES6 समतल का वर्णन करता है
निशिचत धनानी

17
सभी समाधान जो reduce+ concatका उपयोग करते हैं वे ओ ((एन ^ 2) / 2) हैं जहां एक स्वीकृत उत्तर के रूप में (बस एक कॉल concat) एक खराब ब्राउज़र पर सबसे अधिक ओ (एन * 2) और ओ (एन) एक पर होगा अच्छा था। इसके अलावा Denys समाधान वास्तविक प्रश्न के लिए अनुकूलित है और 2x से एकल तक तेज है concat। के लिए reduceयह मजेदार शांत छोटे कोड लिखने लेकिन उदाहरण के लिए महसूस करने के लिए लोगों को यदि सरणी था 1000 एक तत्व subarrays सभी को कम + concat समाधान कर रहे होते 500,500 संचालन जहां एकल concat या साधारण पाश 1000 संचालन करना होगा के रूप में।
जमन

11
बस उपयोगकर्ता फैल ऑपरेटर[].concat(...array)
ओलेग डेटर

@gman कैसे घटाता है + समतल घोल O ((N ^ 2) / 2)? stackoverflow.com/questions/52752666/… एक अलग जटिलता का उल्लेख करता है।
उस्मान

3
ES2019 का समर्थन करने वाले नवीनतम ब्राउज़रों के साथ : array.flat(Infinity)जहां Infinityसमतल करने के लिए अधिकतम गहराई है।
टिमोथी गु

जवाबों:


1860

आप concatसरणियों को मर्ज करने के लिए उपयोग कर सकते हैं :

var arrays = [
  ["$6"],
  ["$12"],
  ["$25"],
  ["$25"],
  ["$18"],
  ["$22"],
  ["$10"]
];
var merged = [].concat.apply([], arrays);

console.log(merged);

वसीयत की applyविधि का उपयोग concatदूसरे पैरामीटर को एक सरणी के रूप में ले जाएगा, इसलिए अंतिम पंक्ति इसके समान है:

var merged2 = [].concat(["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]);

वहाँ भी Array.prototype.flat()विधि (ES2019 में पेश किया गया है) जो आप सरणियों को समतल करने के लिए उपयोग कर सकते हैं, हालांकि यह केवल Node.js में उपलब्ध है जो संस्करण 11 से शुरू होता है, और इंटरनेट एक्सप्लोरर में बिल्कुल भी नहीं

const arrays = [
      ["$6"],
      ["$12"],
      ["$25"],
      ["$25"],
      ["$18"],
      ["$22"],
      ["$10"]
    ];
const merge3 = arrays.flat(1); //The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
console.log(merge3);
    


10
ध्यान दें कि concatस्रोत सरणी को संशोधित नहीं करता है, इसलिए mergedकॉल के बाद सरणी खाली रहेगी concat। कुछ इस तरह कहना बेहतर होगा:merged = merged.concat.apply(merged, arrays);
नैट

65
var merged = [].concat.apply([], arrays);एक लाइन पर लाने के लिए ठीक काम करने लगता है। संपादित करें: जैसा कि निकिता का जवाब पहले से ही दिखाता है।
सीन

44
या Array.prototype.concat.apply([], arrays)
danhbear

30
नोट: यह उत्तर केवल एक स्तर गहरा समतल करता है। पुनरावर्ती समतल के लिए, @Trindaz द्वारा उत्तर देखें।
फोग्ज

208
@ सीन की टिप्पणी के आगे: ES6 वाक्य रचना इस सुपर संक्षिप्त बनाता है:var merged = [].concat(...arrays)
सेठी

505

यहां एक छोटा फ़ंक्शन है जो एन-आयामी सरणी को समतल करने के लिए कुछ नए जावास्क्रिप्ट सरणी तरीकों का उपयोग करता है।

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []);
}

उपयोग:

flatten([[1, 2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]

17
मुझे यह तरीका पसंद है। यह बहुत अधिक सामान्य है और नेस्टेड सरणियों का समर्थन करता है
अल्फ्रेडोकेमबेरा

10
इस समाधान के लिए मेमोरी उपयोग प्रोफ़ाइल क्या है? ऐसा लगता है कि यह पूंछ पुनरावृत्ति के दौरान बहुत सारे मध्यवर्ती सरणियों का निर्माण करता है ....
JBRWilkinson

7
@ संजय, यह कम फ़ंक्शन के लिए शुरुआती संचयकर्ता मूल्य है, जिसे mdn प्रारंभिक मूल्य कहता है। इस मामले में यह flatगुमनाम समारोह के लिए पहली कॉल में मूल्य है reduce। यदि यह निर्दिष्ट नहीं है, तो पहली कॉल reduceसरणी से पहले मूल्य को बाहर करने के लिए बाध्य करती है flat, जिसके परिणामस्वरूप अंततः दोनों उदाहरणों में 1बाध्य किया जाएगा flat1.concatकोई फ़ंक्शन नहीं है।
नूह फ्रीटास

19
या छोटे, कामुक रूप में: const flatten = (arr) => arr.reduce((flat, next) => flat.concat(next), []);
Tsvetomir Tsonev

12
मनमाने ढंग से घोंसले के लिए @TsvetomirTsonev और नोआ समाधान पर riffing:const flatten = (arr) => arr.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
विल

314

एक भ्रामक रूप से छिपी हुई विधि है, जो मूल एक को परिवर्तित किए बिना एक नई सरणी का निर्माण करती है:

var oldArray = [[1],[2,3],[4]];
var newArray = Array.prototype.concat.apply([], oldArray);
console.log(newArray); // [ 1, 2, 3, 4 ]


11
CoffeeScript में यह है[].concat([[1],[2,3],[4]]...)
amoebe

8
@amoebe आपका जवाब [[1],[2,3],[4]]एक परिणाम के रूप में देता है । @ नीकिता जो समाधान देती है वह कॉफीस्क्रिप्ट के साथ-साथ जेएस के लिए भी सही है।
रयान कैनेडी

5
आह, मुझे आपकी त्रुटि मिली। आपके अंकन में वर्ग कोष्ठक की एक अतिरिक्त जोड़ी है, होनी चाहिए [].concat([1],[2,3],[4],...)
रयान कैनेडी

21
मुझे लगता है कि मुझे आपकी त्रुटि भी मिली। ...वास्तविक कोड, नहीं कुछ अंडाकार बिंदु हैं।
एमोबे

3
लाइब्रेरी फंक्शन का उपयोग करने का मतलब यह नहीं है कि कोई कम जरूरी "गड़बड़" है। बस यह कि गंदगी एक पुस्तकालय के अंदर छिपी हुई है। जाहिर है कि लाइब्रेरी का उपयोग करना अपने स्वयं के फ़ंक्शन को रोल करने से बेहतर है, लेकिन यह दावा करना कि यह तकनीक "अनिवार्य गड़बड़ी" को कम करती है बहुत मूर्खतापूर्ण है।
पलडिपिंड

204

यह जावास्क्रिप्ट कम फ़ंक्शन द्वारा सबसे अच्छा किया जा सकता है।

var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];

arrays = arrays.reduce(function(a, b){
     return a.concat(b);
}, []);

या, ES2015 के साथ:

arrays = arrays.reduce((a, b) => a.concat(b), []);

js-बेला

मोज़िला डॉक्स


1
@ जॉन्स वास्तव में प्रति टर्न एक एकल (सरणी) मान पर फ़ीड को कम करते हैं। सबूत? कम करें () और देखें कि क्या यह काम करता है। कम करना () यहाँ Function.prototype.apply () के लिए एक विकल्प है
André Werlang

3
मैंने कम भी इस्तेमाल किया होगा, लेकिन एक दिलचस्प बात जो मैंने इस स्निपेट से सीखी है, वह यह है कि ज्यादातर समय आपको शुरुआती दौर में गुजरने की जरूरत नहीं है :)
जोस एफ। रोमिलिएलो

2
कमी के साथ समस्या यह है कि सरणी खाली नहीं हो सकती है, इसलिए आपको एक अतिरिक्त सत्यापन जोड़ने की आवश्यकता होगी।
रॉबर्ट

4
@calbertts बस प्रारंभिक मान पास करें []और आगे कोई सत्यापन आवश्यक नहीं है।

7
चूंकि आप ES6 का उपयोग करते हैं, इसलिए आप प्रसार-संचालक का उपयोग सरणी शाब्दिक के रूप में भी कर सकते हैं । arrays.reduce((flatten, arr) => [...flatten, ...arr])
पुटजी सैन

108

ऐसा करने के लिए फ्लैट नामक एक नई मूल विधि है।

(2019 के अंत में, flatअब ECMA 2019 के मानक में प्रकाशित किया गया है, और core-js@3(बाबेल के पुस्तकालय) इसे अपने पॉलीफ़िश लाइब्रेरी में शामिल करते हैं )

const arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

// Flatten 2 levels deep
const arr3 = [2, 2, 5, [5, [5, [6]], 7]];
arr3.flat(2);
// [2, 2, 5, 5, 5, [6], 7];

// Flatten all levels
const arr4 = [2, 2, 5, [5, [5, [6]], 7]];
arr4.flat(Infinity);
// [2, 2, 5, 5, 5, 6, 7];

4
यह शर्म की बात है कि यह जवाब के पहले पृष्ठ पर भी नहीं है। यह सुविधा क्रोम 69 और फ़ायरफ़ॉक्स 62 (और बैकएंड में काम करने वालों के लिए नोड 11) में उपलब्ध है
मैट एम।


2
-1; नहीं, यह ECMAScript 2018 का हिस्सा नहीं है । यह अभी भी केवल एक प्रस्ताव है जिसने इसे किसी भी ECMAScript युक्ति से नहीं बनाया है।
मार्क अमेरी

1
मुझे लगता है कि अब हम इस पर विचार कर सकते हैं .. क्योंकि अब यह मानक (2019) का हिस्सा है .. क्या हम इस के प्रदर्शन भाग को एक बार फिर से देख सकते हैं?
युवराज १६'१

ऐसा लगता है कि यह अभी तक किसी भी Microsoft ब्राउज़र द्वारा समर्थित नहीं है (कम से कम उस समय जब मैं यह टिप्पणी लिखता हूं)
लॉरेंट एस।

78

यहां अधिकांश उत्तर विशाल (जैसे 200 000 तत्व) सरणियों पर काम नहीं करते हैं, और यहां तक ​​कि अगर वे करते हैं, तो वे धीमे होते हैं। polkovnikov.ph का उत्तर में सबसे अच्छा प्रदर्शन है, लेकिन यह गहरी लिए काम नहीं करता है।

यहाँ सबसे तेज़ समाधान है, जो नेस्टिंग के कई स्तरों के साथ सरणियों पर भी काम करता है :

const flatten = function(arr, result = []) {
  for (let i = 0, length = arr.length; i < length; i++) {
    const value = arr[i];
    if (Array.isArray(value)) {
      flatten(value, result);
    } else {
      result.push(value);
    }
  }
  return result;
};

उदाहरण

बहुत बड़ा बकाया है

flatten(Array(200000).fill([1]));

यह ठीक ठीक विशाल सरणियों को संभालता है। मेरी मशीन पर इस कोड को निष्पादित करने में लगभग 14 एमएस लगते हैं।

नेस्टेड ऐरे

flatten(Array(2).fill(Array(2).fill(Array(2).fill([1]))));

यह नेस्टेड सरणियों के साथ काम करता है। यह कोड उत्पन्न करता है [1, 1, 1, 1, 1, 1, 1, 1]

घोंसले के शिकार के विभिन्न स्तरों के साथ आता है

flatten([1, [1], [[1]]]);

यह इस तरह चपटे सरणियों के साथ कोई समस्या नहीं है।


अपने विशाल सरणी को छोड़कर बहुत सपाट है। यह समाधान गहरी नेस्टेड सरणियों के लिए काम नहीं करेगा। कोई पुनरावर्ती समाधान नहीं होगा। वास्तव में कोई ब्राउज़र नहीं है, लेकिन सफारी में अभी TCO है, इसलिए कोई पुनरावर्ती एल्गोरिथ्म अच्छा प्रदर्शन नहीं करेगा।
nitely

@ ईमानदारी से, लेकिन वास्तविक दुनिया की स्थिति में आपको घोंसले के शिकार के कुछ स्तरों से अधिक क्या होगा?
माइकल पेर्लोकोस्की

2
आमतौर पर, जब सरणी उपयोगकर्ता द्वारा तैयार की गई सामग्री से उत्पन्न होती है।
नटली

@ 0xcaff क्रोम में यह 200 000-एलिमेंट एरे (आपको मिलता है RangeError: Maximum call stack size exceeded) के साथ काम नहीं करता है । 20 000-तत्व सरणी के लिए यह 2-5 मिलीसेकंड लेता है।
माइकल पेरोलाकोव्स्की

3
इस का O नोटेशन जटिलता क्या है?
जॉर्ज कैटसनोस

58

अद्यतन: यह पता चला है कि यह समाधान बड़े सरणियों के साथ काम नहीं करता है। यह एक बेहतर, तेज़ समाधान की तलाश में है, इस उत्तर को देखें


function flatten(arr) {
  return [].concat(...arr)
}

बस विस्तार होता है arrऔर इसे तर्क के रूप में पारित करता है concat(), जो सभी सरणियों को एक में मिला देता है। इसके बराबर है [].concat.apply([], arr)

तुम भी गहरी चपटे के लिए यह कोशिश कर सकते हैं:

function deepFlatten(arr) {
  return flatten(           // return shalowly flattened array
    arr.map(x=>             // with each x in array
      Array.isArray(x)      // is x an array?
        ? deepFlatten(x)    // if yes, return deeply flattened x
        : x                 // if no, return just x
    )
  )
}

JSBin पर डेमो देखें ।

इस उत्तर में उपयोग किए जाने वाले ECMAScript 6 तत्वों के संदर्भ:


साइड नोट: find()सभी ब्राउज़र द्वारा तीर की तरह कार्य और तरीके समर्थित नहीं हैं, लेकिन इसका मतलब यह नहीं है कि आप अभी इन सुविधाओं का उपयोग नहीं कर सकते हैं। बस बैबेल का उपयोग करें - यह ईएस 6 कोड को ईएस 5 में बदल देता है।


क्योंकि यहाँ लगभग सभी उत्तर applyइस तरह से दुरुपयोग करते हैं , मैंने आपकी टिप्पणियों को आपसे हटा दिया। मुझे अभी भी लगता है कि applyइस तरह से उपयोग करना / फैलाना बुरी सलाह है, लेकिन चूंकि कोई भी परवाह नहीं करता ...

@ LUH3417 यह ऐसा नहीं है, मैं वास्तव में आपकी टिप्पणियों की सराहना करता हूं। यह पता चला कि आप सही हैं - यह समाधान वास्तव में बड़े सरणियों के साथ काम नहीं करता है। मैंने एक और उत्तर पोस्ट किया जो 200 000 तत्वों के सरणियों के साथ भी ठीक काम करता है।
मिशैल पेरोलाकोव्स्की

यदि आप const flatten = arr => [].concat(...arr)
ईएस

आपका क्या मतलब है "बड़े सरणियों के साथ काम नहीं करता है"? कितना बड़ा? क्या होता है?
GEMI

4
@GEMI उदाहरण के लिए इस विधि का उपयोग करके 500000-तत्व सरणी को समतल करने की कोशिश करना "रेंजर्रर: अधिकतम कॉल स्टैक आकार को पार कर गया"।
मीकल पेरोलाकोस्की

51

आप अंडरस्कोर का उपयोग कर सकते हैं :

var x = [[1], [2], [3, 4]];

_.flatten(x); // => [1, 2, 3, 4]

20
वाह, क्या किसी ने जेएस में पर्ल को जोड़ा? :-)
JBRWilkinson

9
@JBRWilkinson शायद JS आपको बहुत अच्छे के लिए एक हास्केल सीखना चाहती है !?
स्टाइल

1+ - आप यह भी निर्दिष्ट कर सकते हैं कि आप दूसरे तर्क के लिए निर्दिष्ट करकेtrue एक उथला चपटा सरणी चाहते हैं ।
जोश क्रोज़ियर

7
@ स्टाइलफेल की टिप्पणी के बारे में पूर्णता की खातिर: learnyouahaskell.com
साइमन ए। यूगस्टर

41

सामान्य प्रक्रियाओं का मतलब है कि हमें किसी विशिष्ट व्यवहार का उपयोग करने के लिए हर बार जटिलता को फिर से लिखना नहीं पड़ता है।

concatMap(या flatMap) वास्तव में इस स्थिति में हमें क्या चाहिए।

// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
  xs.concat (ys)

// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
  xs.map(f).reduce(concat, [])

// id :: a -> a
const id = x =>
  x

// flatten :: [[a]] -> [a]
const flatten =
  concatMap (id)

// your sample data
const data =
  [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]

console.log (flatten (data))

दूरदर्शिता

और हां, आपने इसे सही तरीके से अनुमान लगाया है, यह केवल एक स्तर को समतल करता है, जो कि वास्तव में यह कैसे काम करना चाहिए

कुछ डेटा सेट की कल्पना करें

// Player :: (String, Number) -> Player
const Player = (name,number) =>
  [ name, number ]

// team :: ( . Player) -> Team
const Team = (...players) =>
  players

// Game :: (Team, Team) -> Game
const Game = (teamA, teamB) =>
  [ teamA, teamB ]

// sample data
const teamA =
  Team (Player ('bob', 5), Player ('alice', 6))

const teamB =
  Team (Player ('ricky', 4), Player ('julian', 2))

const game =
  Game (teamA, teamB)

console.log (game)
// [ [ [ 'bob', 5 ], [ 'alice', 6 ] ],
//   [ [ 'ricky', 4 ], [ 'julian', 2 ] ] ]

ठीक है, अब कहते हैं कि हम एक रोस्टर प्रिंट करना चाहते हैं जो सभी खिलाड़ियों को दिखाता है game...

const gamePlayers = game =>
  flatten (game)

gamePlayers (game)
// => [ [ 'bob', 5 ], [ 'alice', 6 ], [ 'ricky', 4 ], [ 'julian', 2 ] ]

यदि हमारी flattenप्रक्रिया नेस्टेड एरेट्स को भी समतल कर दिया है, तो हम इस कचरा परिणाम को समाप्त कर देंगे ...

const gamePlayers = game =>
  badGenericFlatten(game)

gamePlayers (game)
// => [ 'bob', 5, 'alice', 6, 'ricky', 4, 'julian', 2 ]

रोलिन डीप, बेबी

यह कहना है कि कभी-कभी आप नेस्टेड ऐरे को समतल नहीं करना चाहते हैं, वह भी - केवल यह कि डिफ़ॉल्ट व्यवहार नहीं होना चाहिए।

हम deepFlattenआसानी के साथ एक प्रक्रिया कर सकते हैं ...

// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
  xs.concat (ys)

// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
  xs.map(f).reduce(concat, [])

// id :: a -> a
const id = x =>
  x

// flatten :: [[a]] -> [a]
const flatten =
  concatMap (id)

// deepFlatten :: [[a]] -> [a]
const deepFlatten =
  concatMap (x =>
    Array.isArray (x) ? deepFlatten (x) : x)

// your sample data
const data =
  [0, [1, [2, [3, [4, 5], 6]]], [7, [8]], 9]

console.log (flatten (data))
// [ 0, 1, [ 2, [ 3, [ 4, 5 ], 6 ] ], 7, [ 8 ], 9 ]

console.log (deepFlatten (data))
// [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

वहाँ। अब आपके पास प्रत्येक काम के लिए एक उपकरण है - एक घोंसले के शिकार के स्तर को कम करने के flattenलिए, और सभी घोंसले को खत्म करने के लिए एक हैdeepFlatten

शायद आप इसे कॉल कर सकते हैं obliterateया nukeयदि आपको नाम पसंद नहीं है deepFlatten


दो बार पुनरावृति मत करो!

बेशक उपरोक्त कार्यान्वयन चतुर और संक्षिप्त हैं, लेकिन .mapएक कॉल का उपयोग करके .reduceइसका मतलब है कि हम वास्तव में आवश्यकता से अधिक पुनरावृत्तियों कर रहे हैं

एक भरोसेमंद कॉम्बीनेटर का उपयोग करके मैं कॉल कर रहा हूं mapReduce, एक minium को पुनरावृत्तियों को बनाए रखने में मदद करता है; यह एक मैपिंग फ़ंक्शन m :: a -> b, एक कम करने वाला फ़ंक्शन लेता है r :: (b,a) ->bऔर एक नया रिडक्शन फ़ंक्शन देता है - यह कॉम्बिनेटर ट्रांसड्यूसर्स के दिल में है ; यदि आप रुचि रखते हैं, तो मैंने उनके बारे में अन्य उत्तर लिखे हैं

// mapReduce = (a -> b, (b,a) -> b, (b,a) -> b)
const mapReduce = (m,r) =>
  (acc,x) => r (acc, m (x))

// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
  xs.reduce (mapReduce (f, concat), [])

// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
  xs.concat (ys)

// id :: a -> a
const id = x =>
  x

// flatten :: [[a]] -> [a]
const flatten =
  concatMap (id)
  
// deepFlatten :: [[a]] -> [a]
const deepFlatten =
  concatMap (x =>
    Array.isArray (x) ? deepFlatten (x) : x)

// your sample data
const data =
  [ [ [ 1, 2 ],
      [ 3, 4 ] ],
    [ [ 5, 6 ],
      [ 7, 8 ] ] ]

console.log (flatten (data))
// [ [ 1. 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]

console.log (deepFlatten (data))
// [ 1, 2, 3, 4, 5, 6, 7, 8 ]


बार-बार, जब मैं आपके उत्तरों को देखता हूं तो मैं उन्हें वापस लेना चाहता हूं, क्योंकि वे बेकार हो गए हैं। बहुत बढ़िया जवाब! concatस्वयं स्टैक को उड़ा नहीं देता है, केवल ...और apply(बहुत बड़ी सरणियों के साथ) करता है। मैंने इसे नहीं देखा। मैं अभी भयानक महसूस करता हूं।

@ LUH3417 आपको भयानक नहीं लगना चाहिए। आप अच्छी तरह से लिखित स्पष्टीकरण के साथ अच्छे उत्तर भी प्रदान करते हैं। यहाँ सब कुछ सीखने का अनुभव है - मैं अक्सर गलतियाँ करता हूँ और बुरे उत्तर भी लिखता हूँ। मैं उन्हें कुछ महीनों में फिर से देखता हूं और सोचता हूं कि "क्या मैं सोच रहा था?" और अंत में पूरी तरह से संशोधित चीजें। कोई जवाब सही नहीं है। हम सभी सीखने की अवस्था पर कुछ बिंदु पर हैं ^ _ ^
धन्यवाद

1
कृपया ध्यान दें कि concatजावास्क्रिप्ट में हास्केल की तुलना में एक अलग अर्थ है। हास्केल concat( [[a]] -> [a]) को flattenजावास्क्रिप्ट में बुलाया जाएगा और इसे foldr (++) [](जावास्क्रिप्ट: foldr(concat) ([])करी कार्यों को मानते हुए) के रूप में लागू किया जाएगा । जावास्क्रिप्ट concatएक अजीब परिशिष्ट है ( (++)हास्केल में), जो दोनों को संभाल सकता है [a] -> [a] -> [a]और a -> [a] -> [a]

मुझे लगता है कि एक बेहतर नाम थे flatMap, क्योंकि यह वही है जो concatMapहै: मोनाड का bindउदाहरण listconcatpMapके रूप में कार्यान्वित किया जाता है foldr ((++) . f) []। जावास्क्रिप्ट में अनुवादित const flatMap = f => foldr(comp(concat) (f)) ([]):। यह निश्चित रूप से आपके कार्यान्वयन के समान है comp

उस एल्गोरिथ्म की जटिलता क्या है?
जॉर्ज कैटसनोस सेप

32

अधिक सामान्य मामले के लिए एक समाधान, जब आपके पास अपने सरणी में कुछ गैर-सरणी तत्व हो सकते हैं।

function flattenArrayOfArrays(a, r){
    if(!r){ r = []}
    for(var i=0; i<a.length; i++){
        if(a[i].constructor == Array){
            r.concat(flattenArrayOfArrays(a[i], r));
        }else{
            r.push(a[i]);
        }
    }
    return r;
}

4
यह दृष्टिकोण JsonPath क्वेरी से प्राप्त परिणाम-सेटों के नेस्टेड सरणी स्वरूप को समतल करने में बहुत प्रभावी था ।
केविनजैंस

1
सरणियों की एक विधि के रूप में जोड़ा गया:Object.defineProperty(Array.prototype,'flatten',{value:function(r){for(var a=this,i=0,r=r||[];i<a.length;++i)if(a[i]!=null)a[i] instanceof Array?a[i].flatten(r):r.push(a[i]);return r}});
Phrogz

यह टूट जाएगा यदि हम मैन्युअल रूप से दूसरे तर्क में पास होते हैं। उदाहरण के लिए, इसे आज़माएँ: flattenArrayOfArrays (arr, 10)या यह flattenArrayOfArrays(arr, [1,[3]]);- उन दूसरे तर्कों को आउटपुट में जोड़ा जाता है।
ओम शंकर

2
यह उत्तर पूर्ण नहीं है! पुनरावृत्ति का परिणाम कभी भी कहीं भी नहीं दिया जाता है, इसलिए पुनरावर्तन का परिणाम खो जाता है
r3wt

1
@ r3wt ने आगे बढ़कर एक फिक्स जोड़ा। आपको जो करने की ज़रूरत है वह सुनिश्चित करें कि आप जो वर्तमान सरणी बनाए रख रहे हैं r, वह वास्तव में पुनरावर्ती से परिणाम प्राप्त करेगा।
अगस्त

29

की reduce(callback[, initialValue])विधि का उपयोग करने के बारे में क्याJavaScript 1.8

list.reduce((p,n) => p.concat(n),[]);

नौकरी करेंगे।


8
[[1], [2,3]].reduce( (a,b) => a.concat(b), [] )ज्यादा सेक्सी है।
गोलटॉप

5
हमारे मामले में दूसरे तर्क की जरूरत नहीं है[[1], [2,3]].reduce( (a,b) => a.concat(b))
उमैर अहमद

29

कार्यात्मक शैली में एक और ECMAScript 6 समाधान:

एक समारोह घोषित करें:

const flatten = arr => arr.reduce(
  (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);

और इसका उपयोग करें:

flatten( [1, [2,3], [4,[5,[6]]]] ) // -> [1,2,3,4,5,6]

 const flatten = arr => arr.reduce(
         (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
       );


console.log( flatten([1, [2,3], [4,[5],[6,[7,8,9],10],11],[12],13]) )

आधुनिक ब्राउज़रों की अंतिम रिलीज़ में उपलब्ध एक मूल फ़ंक्शन Array.prototyp.flat () (ES6 के लिए प्रस्ताव ) पर विचार करें । @ (Константин Ван) और @ (मार्क अमेरी) के लिए धन्यवाद ने टिप्पणियों में इसका उल्लेख किया।

flatसमारोह एक पैरामीटर, सरणी घोंसले, जो बराबर होती है की उम्मीद की गहराई को निर्दिष्ट है 1डिफ़ॉल्ट रूप से।

[1, 2, [3, 4]].flat();                  // -> [1, 2, 3, 4]

[1, 2, [3, 4, [5, 6]]].flat();          // -> [1, 2, 3, 4, [5, 6]]

[1, 2, [3, 4, [5, 6]]].flat(2);         // -> [1, 2, 3, 4, 5, 6]

[1, 2, [3, 4, [5, 6]]].flat(Infinity);  // -> [1, 2, 3, 4, 5, 6]

let arr = [1, 2, [3, 4]];

console.log( arr.flat() );

arr =  [1, 2, [3, 4, [5, 6]]];

console.log( arr.flat() );
console.log( arr.flat(1) );
console.log( arr.flat(2) );
console.log( arr.flat(Infinity) );


3
यह अच्छा और साफ-सुथरा है लेकिन मुझे लगता है कि आपने ES6 ओवरडोज किया है। एरो-फंक्शन होने के लिए बाहरी फ़ंक्शन की कोई आवश्यकता नहीं है। मैं कॉलबैक को कम करने के लिए एरो-फंक्शन के साथ रहना चाहता हूँ, लेकिन एक सामान्य फंक्शन होना चाहिए।
स्टीफन सिम्पसन

3
@StephenSimpson लेकिन गैर- एरो-फ़ंक्शन होने के लिए बाहरी फ़ंक्शन की आवश्यकता है ? "समतल खुद को एक सामान्य कार्य होना चाहिए" - "सामान्य" से आपका मतलब "गैर-तीर" है, लेकिन क्यों? तब कम करने के लिए कॉल में तीर फ़ंक्शन का उपयोग क्यों करें? आप तर्क की अपनी लाइन की आपूर्ति कर सकते हैं?
धन्यवाद

@naomik मेरा तर्क यह है कि यह अनावश्यक है। यह मुख्य रूप से शैली की बात है; मुझे अपनी टिप्पणी में बहुत स्पष्ट होना चाहिए। एक या दूसरे का उपयोग करने का कोई प्रमुख कोडिंग कारण नहीं है। हालांकि, फ़ंक्शन को गैर-तीर के रूप में देखना और पढ़ना आसान है। आंतरिक फ़ंक्शन एक तीर फ़ंक्शन के रूप में उपयोगी है क्योंकि यह अधिक कॉम्पैक्ट है (और निश्चित रूप से कोई संदर्भ नहीं बनाया गया है)। एरो फ़ंक्शंस, फ़ंक्शन को पढ़ने और इस भ्रम से बचने के लिए कॉम्पैक्ट आसान बनाने के लिए महान हैं। हालांकि, वे वास्तव में यह पढ़ना और अधिक कठिन बना सकते हैं जब एक गैर-तीर पर्याप्त होगा। हालांकि अन्य असहमत हो सकते हैं!
स्टीफन सिम्पसन

एकRangeError: Maximum call stack size exceeded
मैट Westlake

@ मैट, कृपया त्रुटि को पुन: उत्पन्न करने के लिए आपके द्वारा उपयोग किए जाने वाले उत्क्रमण को साझा करें
diziaq

28

एकल तत्व सरणियों के एक सरणी को समतल करने के लिए, आपको एक पुस्तकालय आयात करने की आवश्यकता नहीं है, एक सरल लूप सरल और सबसे कुशल समाधान दोनों है :

for (var i = 0; i < a.length; i++) {
  a[i] = a[i][0];
}

डाउनवोटर्स के लिए: कृपया सवाल पढ़ें, डाउनवोट न करें क्योंकि यह आपकी बहुत अलग समस्या के अनुरूप नहीं है। यह समाधान पूछे गए प्रश्न के लिए सबसे तेज और सरल दोनों है।


4
मैं कहूंगा, "चीजों को अधिक गूढ़ मत देखो।" ^ ^

4
मेरा मतलब है ... जब मैं लोगों को उस के लिए एक पुस्तकालय ... वह पागल है ... उपयोग करने के लिए सलाह देने को देखने
डेनिस Séguret

3
आह, एक पुस्तकालय का उपयोग करने के बस के लिए यह मूर्खतापूर्ण होगा ... लेकिन अगर यह पहले से ही उपलब्ध है।

9
@dystroy लूप के लिए सशर्त भाग वह पठनीय नहीं है। या यह सिर्फ मुझे है: डी
एंड्रियास

4
यह वास्तव में कोई फर्क नहीं पड़ता कि यह कितना गूढ़ है। इस कोड को "समतल" किया ['foo', ['bar']]जाता है ['f', 'bar']
jonschlinkert

22
const common = arr.reduce((a, b) => [...a, ...b], [])

यह है कि मैं इसे अपने कोड में कैसे करता हूं, लेकिन मुझे यकीन नहीं है कि अगर आप एक बहुत लंबी सरणी रखते हैं तो गति स्वीकार किए गए उत्तर की तुलना कैसे करती है
माइकल आरोन विल्सन

14

कृपया ध्यान दें: जब Function.prototype.apply( [].concat.apply([], arrays)) या प्रसार ऑपरेटर ( [].concat(...arrays)) का उपयोग किसी सरणी को समतल करने के लिए किया जाता है, तो दोनों बड़े सरणियों के लिए स्टैक ओवरफ्लो का कारण बन सकते हैं, क्योंकि फ़ंक्शन का प्रत्येक तर्क स्टैक पर संग्रहीत होता है।

यहां कार्यात्मक शैली में एक स्टैक-सुरक्षित कार्यान्वयन है जो एक दूसरे के खिलाफ सबसे महत्वपूर्ण आवश्यकताओं का वजन करता है:

  • पुनर्प्रयोग
  • पठनीयता
  • संक्षिप्ति
  • प्रदर्शन

// small, reusable auxiliary functions:

const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); // aka reduce

const uncurry = f => (a, b) => f(a) (b);

const concat = xs => y => xs.concat(y);


// the actual function to flatten an array - a self-explanatory one-line:

const flatten = xs => foldl(concat) ([]) (xs);

// arbitrary array sizes (until the heap blows up :D)

const xs = [[1,2,3],[4,5,6],[7,8,9]];

console.log(flatten(xs));


// Deriving a recursive solution for deeply nested arrays is trivially now


// yet more small, reusable auxiliary functions:

const map = f => xs => xs.map(apply(f));

const apply = f => a => f(a);

const isArray = Array.isArray;


// the derived recursive function:

const flattenr = xs => flatten(map(x => isArray(x) ? flattenr(x) : x) (xs));

const ys = [1,[2,[3,[4,[5],6,],7],8],9];

console.log(flattenr(ys));

जैसे ही आपको छोटे तीर के कार्य करने की आदत हो जाती है, फ़ंक्शन रचना और उच्च क्रम फ़ंक्शन के रूप में, यह कोड गद्य की तरह पढ़ता है। प्रोग्रामिंग तब केवल छोटे बिल्डिंग ब्लॉक्स को एक साथ रखने में होती है जो हमेशा अपेक्षित रूप से काम करते हैं, क्योंकि उनमें कोई दुष्प्रभाव नहीं होता है।


1
Haha। अपने जवाब का पूरी तरह से सम्मान करें, हालांकि इस तरह कार्यात्मक प्रोग्रामिंग पढ़ना अभी भी मुझे (अंग्रेजी बोलने वाले) चरित्र द्वारा जापानी चरित्र पढ़ना पसंद है।
टारविन स्ट्रोह-स्पाइजर

2
यदि आप अपने आप को भाषा A में भाषा A की विशेषताओं को कार्यान्वित करते हुए पाते हैं, परियोजना के एक भाग के रूप में नहीं है, तो ऐसा करने का एकमात्र लक्ष्य है। क्या आप यह बन सकते हो? बस साथ जाने const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);से आपको दृश्य कचरा और अपने साथियों को स्पष्टीकरण मिलता है कि आपको 3 अतिरिक्त कार्यों और कुछ फ़ंक्शन कॉल की आवश्यकता क्यों है।
Daerdemandt

3
@Daerdemandt लेकिन यदि आप इसे अलग-अलग फ़ंक्शन के रूप में लिखते हैं, तो आप संभवतः उन्हें अन्य कोड में पुन: उपयोग कर पाएंगे।
मिशैल पेरोलाकोव्स्की

@ MichałPerłakowski यदि आपको उन्हें कई स्थानों पर उपयोग करने की आवश्यकता है, तो पहिया को सुदृढ़ न करें और इनमें से एक पैकेज चुनें - प्रलेखित और अन्य लोगों द्वारा समर्थित।
दिरडेमंड्ट

12

ईएस 6 वन लाइन फ्लैटन

देखें फ्लैश फ्लैटन , अंडरस्कोर फ्लैटन (उथले true)

function flatten(arr) {
  return arr.reduce((acc, e) => acc.concat(e), []);
}

या

function flatten(arr) {
  return [].concat.apply([], arr);
}

के साथ परीक्षण किया गया

test('already flatted', () => {
  expect(flatten([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});

test('flats first level', () => {
  expect(flatten([1, [2, [3, [4]], 5]])).toEqual([1, 2, [3, [4]], 5]);
});

ईएस 6 वन लाइन डीप फ्लैटन

देखिए फ्लैश फ्लैटनडिप , अंडरस्कोर फ्लैटन

function flattenDeep(arr) {
  return arr.reduce((acc, e) => Array.isArray(e) ? acc.concat(flattenDeep(e)) : acc.concat(e), []);
}

के साथ परीक्षण किया गया

test('already flatted', () => {
  expect(flattenDeep([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});

test('flats', () => {
  expect(flattenDeep([1, [2, [3, [4]], 5]])).toEqual([1, 2, 3, 4, 5]);
});

आपका दूसरा उदाहरण बेहतर लिखा गया है Array.prototype.concat.apply([], arr)क्योंकि आप concatफ़ंक्शन को प्राप्त करने के लिए एक अतिरिक्त सरणी बनाते हैं । रनमाइंट इसे चलाने के दौरान इसे दूर नहीं कर सकते हैं या नहीं कर सकते हैं, लेकिन प्रोटोटाइप पर फ़ंक्शन तक पहुंचने से यह किसी भी मामले में पहले से ही कोई भी बदसूरत नहीं दिखता है।
मोरे

11

आप उपयोग कर सकते हैं Array.flat()के साथ Infinityनेस्टेड सरणी के किसी भी गहराई के लिए।

var arr = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]], [[1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]]] ];

let flatten = arr.flat(Infinity)

console.log(flatten)

ब्राउज़र संगतता के लिए यहां देखें


8

एक हास्कलेस्क दृष्टिकोण

function flatArray([x,...xs]){
  return x ? [...Array.isArray(x) ? flatArray(x) : [x], ...flatArray(xs)] : [];
}

var na = [[1,2],[3,[4,5]],[6,7,[[[8],9]]],10];
    fa = flatArray(na);
console.log(fa);


1
@Monners से सहमत हैं। इस पूरे धागे में सबसे सुरुचिपूर्ण समाधान नीचे हाथ।
निकोलस फंताट

8

ES6 रास्ता:

const flatten = arr => arr.reduce((acc, next) => acc.concat(Array.isArray(next) ? flatten(next) : next), [])

const a = [1, [2, [3, [4, [5]]]]]
console.log(flatten(a))

N3 flattenनेस्टेड एरेज़ के लिए ES3 फॉलबैक के साथ फंक्शन के लिए ES5 रास्ता :

var flatten = (function() {
  if (!!Array.prototype.reduce && !!Array.isArray) {
    return function(array) {
      return array.reduce(function(prev, next) {
        return prev.concat(Array.isArray(next) ? flatten(next) : next);
      }, []);
    };
  } else {
    return function(array) {
      var arr = [];
      var i = 0;
      var len = array.length;
      var target;

      for (; i < len; i++) {
        target = array[i];
        arr = arr.concat(
          (Object.prototype.toString.call(target) === '[object Array]') ? flatten(target) : target
        );
      }

      return arr;
    };
  }
}());

var a = [1, [2, [3, [4, [5]]]]];
console.log(flatten(a));


7

यदि आपके पास केवल 1 स्ट्रिंग तत्व के साथ सरणियाँ हैं:

[["$6"], ["$12"], ["$25"], ["$25"]].join(',').split(',');

नौकरी करेंगे। बीटी जो विशेष रूप से आपके कोड उदाहरण से मेल खाता है।


3
जिसने भी मतदान किया है, कृपया उसे समझाएं। मैं एक अच्छे समाधान की तलाश कर रहा था और उन सभी समाधानों में से जो मुझे सबसे ज्यादा पसंद थे।
बेनामी

2
@ अज्ञात मैंने इसे कम नहीं किया क्योंकि यह तकनीकी रूप से प्रश्न की आवश्यकताओं को पूरा करता है, लेकिन इसकी संभावना है क्योंकि यह एक बहुत ही खराब समाधान है जो सामान्य मामले में उपयोगी नहीं है। यह देखते हुए कि यहां कितने बेहतर समाधान हैं, मैं कभी किसी को इस के साथ जाने की सलाह नहीं दूंगा क्योंकि यह उस क्षण को तोड़ देता है जब आपके पास एक से अधिक तत्व होते हैं, या जब वे तार नहीं होते हैं।
Thor84no

2
मुझे यह समाधान पसंद है =)
ह्यूई टैन

2
यह केवल 1 स्ट्रिंग तत्वों के साथ सरणियों को संभालता नहीं है, यह इस सरणी को भी संभालता है ['$4', ["$6"], ["$12"], ["$25"], ["$25", "$33", ['$45']]].join(',').split(',')
alucic

मैंने अपने आप ही इस विधि की खोज की, हालाँकि यह जानता था कि यह पहले ही कहीं दस्तावेज हो चुका होगा, मेरी खोज यहाँ समाप्त हुई। इस समाधान के साथ दोष यह है कि यह संख्या, बूलियन आदि को तार से [1,4, [45, 't', ['e3', 6]]].toString().split(',')[1,4, [45, 't', ['e3', 6], false]].toString().split(',')
सहलाता है

7
var arrays = [["a"], ["b", "c"]];
Array.prototype.concat.apply([], arrays);

// gives ["a", "b", "c"]

(मैं इसे केवल एक अलग उत्तर के रूप में लिख रहा हूं, जो @danhbear की टिप्पणी पर आधारित है।)


7

मैं एक अंतरिक्ष-कुशल जनरेटर फ़ंक्शन की सलाह देता हूं :

function* flatten(arr) {
  if (!Array.isArray(arr)) yield arr;
  else for (let el of arr) yield* flatten(el);
}

// Example:
console.log(...flatten([1,[2,[3,[4]]]])); // 1 2 3 4

यदि वांछित है, तो निम्नानुसार चपटा मानों की एक सरणी बनाएं:

let flattened = [...flatten([1,[2,[3,[4]]]])]; // [1, 2, 3, 4]

मुझे यह तरीका पसंद है। करने के लिए इसी तरह के stackoverflow.com/a/35073573/1175496 , लेकिन प्रसार ऑपरेटर का उपयोग करता है ...जनरेटर के माध्यम से पुनरावृति।
रेड मटर

6

मैं इसके बजाय पूरे सरणी को बदल दूंगा, जैसा कि, एक स्ट्रिंग के लिए, लेकिन अन्य उत्तरों के विपरीत, यह होगा कि विधि JSON.stringifyका उपयोग और उपयोग न करें toString(), जो एक अवांछित परिणाम उत्पन्न करता है।

उस JSON.stringifyआउटपुट के साथ , जो कुछ बचा है वह सभी ब्रैकेट को हटाने के लिए है, परिणाम को फिर से शुरू और समाप्त करने वाले ब्रैकेट के साथ लपेटें, और परिणाम की सेवा करें जिसके साथ JSON.parseस्ट्रिंग को "जीवन" में वापस लाया जाए।

  • बिना किसी गति लागत के अनंत नेस्टेड सरणियों को संभाल सकता है।
  • सही रूप से एरे आइटम को संभाल सकते हैं जो कॉमा से युक्त तार हैं।

var arr = ["abc",[[[6]]],["3,4"],"2"];

var s = "[" + JSON.stringify(arr).replace(/\[|]/g,'') +"]";
var flattened = JSON.parse(s);

console.log(flattened)

  • केवल स्ट्रिंग्स / नंबरों के बहुआयामी ऐरे के लिए (ऑब्जेक्ट्स नहीं)

आपका समाधान गलत है। इसमें कॉमा शामिल होगा जब आंतरिक ["345", "2", "3,4", "2"]मूल्यों को अलग करने के बजाय उन प्रत्येक मूल्यों को अलग करने के लिए अलग-अलग सूचकांकों को अलग करना होगा
पिज्जाब्रो

@realseanp - आप उस ऐरे आइटम में मान गलत समझे। मैंने जानबूझकर उस अल्पविराम को एक मूल्य के रूप में रखा था न कि किसी अन्य के रूप में मेरे समाधान की शक्ति पर जोर देने के लिए एरियर सीमांकक अल्पविराम के रूप में "3,4"
vsync

1
मैंने गलत समझा
पिज़्ज़ा नर्व

ऐसा लगता है कि निश्चित रूप से इसके लिए मैंने सबसे तेज़ समाधान देखा है; क्या आप किसी भी नुकसान के बारे में जानते हैं @vsync (इस तथ्य को छोड़कर, यह पाठ्यक्रम की थोड़ी सी हैकेटी है - नेस्टेड एरेज़ को स्ट्रिंग्स के रूप में व्यवहार करना: डी)
जॉर्ज कैटसनोस

@GeorgeKatsanos - यह विधि सरणी आइटम (और नेस्टेड आइटम) के लिए काम नहीं करेगी जो कि आदिम मूल्य के नहीं हैं, उदाहरण के लिए एक आइटम जो एक DOM तत्व को इंगित करता है
vsync

6

आप नई Array.Flat()विधि भी आजमा सकते हैं । यह निम्नलिखित तरीके से काम करता है:

let arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]].flat()

console.log(arr);

यह flat()विधि सभी उप-सरणी तत्वों के साथ एक नया सरणी बनाती है, जो इसे गहराई तक 1 परत तक ले जाती है (यानी सरणियों के अंदर सरण)

यदि आप 3 आयामी या उच्चतर आयामी सरणियों को भी समतल करना चाहते हैं, तो आप बस फ्लैट विधि को कई बार कॉल करते हैं। उदाहरण के लिए (3 आयाम):

let arr = [1,2,[3,4,[5,6]]].flat().flat().flat();

console.log(arr);

सावधान रहे!

Array.Flat()तरीका अपेक्षाकृत नया है। पुराने ब्राउज़र जैसे कि विधि ने लागू नहीं किया हो सकता है। यदि आप चाहते हैं कि आप सभी ब्राउज़रों पर काम करें तो आपको अपने जेएस को पुराने संस्करण में ट्रांसप्लांट करना पड़ सकता है। वर्तमान ब्राउज़र संगतता के लिए एमडी वेब डॉक्स के लिए जाँच करें।


2
फ्लैट उच्च आयामी सरणियों के लिए आप बस Infinityतर्क के साथ फ्लैट विधि कॉल कर सकते हैं । इस तरह:arr.flat(Infinity)
मिखाइल

यह एक बहुत अच्छा जोड़ है, धन्यवाद मिखाइल!
विलेम वैन डेर वीन


5

यह मुश्किल नहीं है, बस सरणियों पर पुनरावृत्ति करें और उन्हें मर्ज करें:

var result = [], input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"]];

for (var i = 0; i < input.length; ++i) {
    result = result.concat(input[i]);
}

5

ऐसा लगता है कि यह RECURSION के लिए एक नौकरी की तरह लग रहा है!

  • घोंसले के शिकार के कई स्तरों को संभालता है
  • खाली सरणियों और गैर सरणी मापदंडों को संभालता है
  • कोई उत्परिवर्तन नहीं है
  • आधुनिक ब्राउज़र सुविधाओं पर निर्भर नहीं है

कोड:

var flatten = function(toFlatten) {
  var isArray = Object.prototype.toString.call(toFlatten) === '[object Array]';

  if (isArray && toFlatten.length > 0) {
    var head = toFlatten[0];
    var tail = toFlatten.slice(1);

    return flatten(head).concat(flatten(tail));
  } else {
    return [].concat(toFlatten);
  }
};

उपयोग:

flatten([1,[2,3],4,[[5,6],7]]);
// Result: [1, 2, 3, 4, 5, 6, 7] 

सावधान, flatten(new Array(15000).fill([1]))फेंकता है Uncaught RangeError: Maximum call stack size exceededऔर 10 सेकंड के लिए मेरे शैतानों को मुक्त कर देता है
पीट्रोविस्मारा

@ पिएट्रोविस्मारा, मेरा परीक्षण 1s के आसपास है।
इवान यान

5

मैंने इसे रिकर्सन और क्लोजर का उपयोग करके किया है

function flatten(arr) {

  var temp = [];

  function recursiveFlatten(arr) { 
    for(var i = 0; i < arr.length; i++) {
      if(Array.isArray(arr[i])) {
        recursiveFlatten(arr[i]);
      } else {
        temp.push(arr[i]);
      }
    }
  }
  recursiveFlatten(arr);
  return temp;
}

1
सरल और मीठा, यह उत्तर स्वीकृत उत्तर की तुलना में बेहतर काम करता है। यह गहराई से करने के लिए ही नहीं, पहले के स्तर के स्तर नेस्ट सपाट
ओम शंकर

1
AFAIK जो कि लेक्सिकल
स्कूपिंग है

@ डशमबल्स सही है - अंतर यह है कि यदि यह बंद था तो आप आंतरिक फ़ंक्शन को बाहर तक लौटा देंगे और जब बाहरी फ़ंक्शन समाप्त हो जाएगा तब भी आप इसके कार्यक्षेत्र तक पहुंचने के लिए आंतरिक फ़ंक्शन का उपयोग कर सकते हैं। यहाँ बाहरी फ़ंक्शन का जीवनकाल आंतरिक फ़ंक्शन की तुलना में लंबा है, इसलिए "बंद" कभी नहीं बनाया जाता है।
मोरे

5

मैं दूसरे दिन ES6 जेनरेटरों के साथ जा रहा था और यह जिस्ट लिखा । जिसमें है...

function flatten(arrayOfArrays=[]){
  function* flatgen() {
    for( let item of arrayOfArrays ) {
      if ( Array.isArray( item )) {
        yield* flatten(item)
      } else {
        yield item
      }
    }
  }

  return [...flatgen()];
}

var flatArray = flatten([[1, [4]],[2],[3]]);
console.log(flatArray);

मूल रूप से मैं एक जनरेटर बना रहा हूं जो मूल इनपुट सरणी पर लूप करता है, अगर यह एक सरणी पाता है तो यह पैदावार * ऑपरेटर को पुनरावृत्ति के साथ संयोजन में आंतरिक सरणियों को लगातार समतल करने के लिए उपयोग करता है। यदि आइटम एक सरणी नहीं है यह सिर्फ पैदावार एक आइटम। फिर ES6 स्प्रेड ऑपरेटर का उपयोग करना (उर्फ स्पैट ऑपरेटर) मैं जनरेटर को एक नए सरणी उदाहरण में समतल करता हूं।

मैंने इसके प्रदर्शन का परीक्षण नहीं किया है, लेकिन मुझे लगता है कि यह जनरेटर और उपज * ऑपरेटर का उपयोग करने का एक अच्छा सरल उदाहरण है।

लेकिन फिर, मैं बस नासमझ था इसलिए मुझे यकीन है कि ऐसा करने के लिए और अधिक प्रदर्शन करने के तरीके हैं।


1
इसी तरह का जवाब (जनरेटर और उपज प्रतिनिधिमंडल का उपयोग करके), लेकिन PHP प्रारूप में
लाल मटर

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