जावास्क्रिप्ट - एक सरणी को दूसरे सरणी के अंदर डालें


87

किसी अन्य सरणी के अंदर एक सरणी डालने के लिए और अधिक कुशल तरीका क्या है।

a1 = [1,2,3,4,5];
a2 = [21,22];

newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];

यदि a2 सरणी बड़ी है, तो स्प्लिट का उपयोग करके a2 को बंटवारे के प्रदर्शन से थोड़ा अजीब लगता है।

धन्यवाद।



2
यह एक आइटम नहीं बल्कि एक सरणी है, इसलिए ब्याह काम नहीं कर रहा है
ic3

जवाबों:


179

आप spliceकुछ applyप्रवंचनाओं के साथ संयुक्त का उपयोग कर सकते हैं :

a1 = [1,2,3,4,5];
a2 = [21,22];

a1.splice.apply(a1, [2, 0].concat(a2));

console.log(a1); // [1, 2, 21, 22, 3, 4, 5];

ES2015 + में, आप इसे थोड़ा अच्छा बनाने के लिए इसके बजाय प्रसार ऑपरेटर का उपयोग कर सकते हैं

a1.splice(2, 0, ...a2);

10
@icCube: मैंने सिर्फ एक बेंचमार्क चलाया, इस पद्धति की तुलना पेट्रिक के उत्तर में की। यह उदाहरण के रूप में a1 और a2 से शुरू होता है, और a2 10,000 को a1 10,000 बार में इंजेक्ट करता है (ताकि अंत में, आपके पास 20,005 तत्वों के साथ एक सरणी हो)। इस विधि ने लिया: 81ms , स्लाइस + कॉन्कैट विधि ने 156ms (क्रोम 13 पर परीक्षण) लिया । बेशक, यह मानक चेतावनी के साथ आता है कि ज्यादातर मामलों में, गति की तुलना में सुगमता अधिक महत्वपूर्ण होगी।
निकफ

3
@ रिक: क्रोम में यदि सरणियाँ 130000 से अधिक आइटम रखती हैं तो स्टैकओवरफ़्लो applyअपवाद को फेंक देगी। jsfiddle.net/DcHCY यह भी होता है कि jsPerf में मुझे FF पर विश्वास है और IE थ्रेशहोल्ड 500k के आसपास है
Nope

आप सीधे कॉल ब्याह का विरोध करने और तर्कों को पारित करने के विरोध में आवेदन क्यों करते हैं?
पीटर पी।

@ फ्रांस्वा वाहल, यह एक गंभीर मुद्दा है जिसे लोग अक्सर उनके जवाब में नजरअंदाज कर देते हैं। मैंने आपका उदाहरण लिया है और 1M तत्वों के उत्तर के साथ काम किया है: stackoverflow.com/a/41466395/1038326
गेब्रियल कोहेन

मैं सिर्फ यह (जून 2017) और दोनों छोटे सरणी आकार और बड़े सरणी आकार के लिए सबसे तेज़ तरीका है की कोशिश की है (क्रोम, एफएफ और किनारे पर) हो गया लगता है target.slice(0, insertIndex).concat(insertArr, target.slice(insertIndex)); jsperf.com/inserting-an-array-within-an-array
एलेक्स दीमा


14

पहले तो गलत हुआ। की concat()जगह इस्तेमाल करना चाहिए था ।

var a1 = [1,2,3,4,5],
    a2 = [21,22],
    startIndex = 0,
    insertionIndex = 2,
    result;    

result = a1.slice(startIndex, insertionIndex).concat(a2).concat(a1.slice(insertionIndex));

उदाहरण: http://jsfiddle.net/f3cae/1/

इस अभिव्यक्ति का उपयोग करता है slice(0, 2)[डॉक्स] के पहले दो तत्वों को वापस करने के लिए a1(जहां 0शुरुआती सूचकांक है, और 2तत्व डिलीट है, हालांकिa1 इसे बदला नहीं गया है)।

इंटरमीडिएट का रिजल्ट :[1,2]

इसके बाद के अंत में संलग्न करने के लिए concat(a2)[डॉक्स] का उपयोग करता a2है[1,2]

इंटरमीडिएट का परिणाम :[1,2,21,22]

इसके बाद, इस अभिव्यक्ति के पूंछ के छोर पर a1.slice(2)एक अनुगामी के भीतर बुलाया जाता है .concat(), जिसकी मात्रा होती है[1,2,21,22].concat(a1.slice(2))

एक कॉल टू slice(2)पॉजिटिव पूर्णांक तर्क, 2 तत्वों के बाद सभी तत्वों को लौटा देगा, प्राकृतिक संख्याओं के साथ गिनती होगी (जैसे कि, पांच तत्व हैं, इसलिए [3,4,5]से वापस आ जाएंगे a1)। यह कहने का एक और तरीका यह है कि एकवचन पूर्णांक सूचकांक तर्क बताता a1.slice()है कि सरणी में किस स्थिति से तत्वों को वापस करना शुरू करना है (सूचकांक 2 तीसरा तत्व है)।

इंटरमीडिएट का परिणाम :[1,2,21,22].concat([3,4,5])

अंत में, दूसरा इसके अंत में .concat()जोड़ता [3,4,5]है [1,2,21,22]

परिणाम :[1,2,21,22,3,4,5]

यह परिवर्तन करने के लिए लुभावना हो सकता है Array.prototype, लेकिन कोई केवल प्रोटोटाइप इनहेरिटेंस का उपयोग करके ऐरे ऑब्जेक्ट का विस्तार कर सकता है और आपके प्रोजेक्ट्स में नई ऑब्जेक्ट को इंजेक्ट कर सकता है।

हालांकि, किनारे पर रहने वालों के लिए ...

उदाहरण: http://jsfiddle.net/f3cae/2/

Array.prototype.injectArray = function( idx, arr ) {
    return this.slice( 0, idx ).concat( arr ).concat( this.slice( idx ) );
};

var a1 = [1,2,3,4,5];
var a2 = [21,22];

var result = a1.injectArray( 2, a2 );

मुझे 6 आइटम 7 के साथ a1 मिलता है -> [1,2, [21,22], 3,4,5]
ic3

काम करता है! बहुत बहुत धन्यवाद, चलो कुछ दिनों तक प्रतीक्षा करें लेकिन यह सबसे अच्छा जवाब है ... अजीब है कि उनके पास इसके लिए एक जेएस फ़ंक्शन नहीं है।
ic3

मुझे यह एक अच्छा लगता है
किम्ची मैन

संक्षेप में, जेएस इंजन को अभिव्यक्ति समाप्त होने से पहले चार सरणियों को वापस करना होगा। मुझे समाधान का तर्क पसंद है, लेकिन यह अंतरिक्ष के विचारों के संदर्भ में इष्टतम नहीं हो सकता है। हालाँकि मैं मानता हूँ कि यह निफ्टी है और बहुत क्रॉस ब्राउज़र संगत है। प्रसार संचालक का उपयोग करने की लागत है, क्योंकि यह संग्रह पर काम करता है, लेकिन मुझे लगता है कि लंबे समय में चार सरणियों को वापस कर सकता है।
एंथनी रटलेज

3

प्रसार ऑपरेटर एक अभिव्यक्ति स्थानों पर जहां कई तर्क या एक से अधिक तत्वों (सरणी शाब्दिक के लिए) (समारोह कॉल के लिए) उम्मीद कर रहे हैं में विस्तार करने की अनुमति देता है।

a2 = [21,22];
a1 = [1,2,...a2,3,4,5];//...a2 is use of spread operator
console.log(a1);


3

इस प्रश्न के कुछ रचनात्मक उत्तर यहां दिए गए हैं। यहाँ उन लोगों के लिए एक सरल समाधान है, जो केवल सरणियों के साथ शुरू करते हैं। यदि वांछित हो, तो ECMAScript 3 के अनुरूप ब्राउज़रों के नीचे काम करने के लिए इसे बनाया जा सकता है।

शुरू करने से पहले ब्याह के बारे में कुछ जान लें।

मोज़िला डेवलपर नेटवर्क: Array.prototyp.splice ()

सबसे पहले, दो महत्वपूर्ण रूपों को समझें .splice()

let a1 = [1,2,3,4],
    a2 = [1,2];

विधि 1) वांछित सूचकांक से शुरू x (डिलीट) तत्वों को हटा दें।

let startIndex = 0, 
    deleteCount = 2;

a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]

विधि 2) सरणी के अंत में वांछित स्टार्ट इंडेक्स के बाद तत्वों को निकालें।

a1.splice(2); // returns [3,4], a1 would be [1,2]

उपयोग करना .splice(), एक लक्ष्य a1ऊपर के दो रूपों में से एक का उपयोग करके सिर और पूंछ सरणियों में विभाजित किया जा सकता है ।

# 1 विधि का उपयोग करके, वापसी मूल्य सिर, और a1पूंछ बन जाएगा ।

let head = a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]

अब, एक झपट्टा में गिर गया, सिर, शरीर ( a2), और पूंछ

[].concat(head, a2, a1);

इस प्रकार, यह समाधान वास्तविक दुनिया की तुलना में कहीं अधिक है जो इस प्रकार अब तक प्रस्तुत किया गया है। क्या आप लेगोस के साथ ऐसा नहीं करेंगे? ;-) यहाँ एक विधि है, # 2 विधि का उपयोग करके।

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
    let tail = target.splice(startIndex); // target is now [1,2] and the head
    return [].concat(target, body, tail);
}

let newArray = insertArray([1, 2, 3, 4], ["a", "b"], 2); // [1, 2, "a", "b", 3, 4]

छोटा:

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
    return [].concat(target, body, target.splice(startIndex));
}

सुरक्षित:

/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*@throws Error The value for startIndex must fall between the first and last index, exclusive.
*/
function insertArray(target, body, startIndex)
{
    const ARRAY_START = 0,
          ARRAY_END = target.length - 1,
          ARRAY_NEG_END = -1,
          START_INDEX_MAGNITUDE = Math.abs(startIndex);

    if (startIndex === ARRAY_START) {
        throw new Error("The value for startIndex cannot be zero (0).");
    }

    if (startIndex === ARRAY_END || startIndex === ARRAY_NEG_END) {
        throw new Error("The startIndex cannot be equal to the last index in target, or -1.");
    }

    if (START_INDEX_MAGNITUDE >= ARRAY_END) {
        throw new Error("The absolute value of startIndex must be less than the last index.");
    }

    return [].concat(target, body, target.splice(startIndex));
}

इस समाधान के लाभों में शामिल हैं:

1) एक सरल आधार समाधान पर हावी है - एक खाली सरणी भरें।

2) सिर, शरीर और पूंछ का नामकरण स्वाभाविक लगता है।

3) कोई डबल कॉल नहीं .slice()। कोई स्लाइसिंग नहीं।

4) नहीं .apply()। अत्यधिक अनावश्यक है।

5) विधि जंजीर से बचा जाता है।

6) ईसीएमएस्क्रिप्ट 3 और 5 में काम करता varहै letया केवल इसके बजाय का उपयोग करके const

** 7) यह सुनिश्चित करता है कि प्रस्तुत किए गए कई अन्य समाधानों के विपरीत, शरीर को थप्पड़ मारने के लिए एक सिर और पूंछ होगी। यदि आप पहले या बाद में एक सरणी जोड़ रहे हैं, तो आपको कम से कम उपयोग करना चाहिए .concat()!!!!

नोट: प्रसार ओपियेटर का उपयोग ...यह पूरा करने के लिए बहुत आसान बनाता है।


2

मैं ऐसा करने के लिए एक रास्ता खोजना चाहता था splice()और कोई पुनरावृति नहीं: http://jsfiddle.net/jfriend00/W9n27/

a1 = [1,2,3,4,5];
a2 = [21,22];

a2.unshift(2, 0);          // put first two params to splice onto front of array
a1.splice.apply(a1, a2);   // pass array as arguments parameter to splice
console.log(a1);           // [1, 2, 21, 22, 3, 4, 5];

सामान्य प्रयोजन फ़ंक्शन में:

function arrayInsertAt(destArray, pos, arrayToInsert) {
    var args = [];
    args.push(pos);                           // where to insert
    args.push(0);                             // nothing to remove
    args = args.concat(arrayToInsert);        // add on array to insert
    destArray.splice.apply(destArray, args);  // splice it in
}

यह a2सरणी को भी संशोधित करता है , जो संभवतः काफी अवांछनीय है। इसके अलावा, Array.prototypeजब आपको स्लाइस फ़ंक्शन ठीक है a1या उस समय पर जाने की आवश्यकता नहीं है a2
निकफ

मुझे पता था कि यह a2 को संशोधित कर रहा था। ओपी तय कर सकता है कि समस्या है या नहीं। क्या विधि प्राप्त करने के लिए प्रोटोटाइप में जाने में कुछ गड़बड़ है? यह मेरे लिए अधिक उपयुक्त लग रहा था क्योंकि मैं सिर्फ विधि चाहता था और वस्तु को apply()विधि में जोड़ा जा रहा था ।
२१

खैर नहीं, यह ठीक उसी तरह का कार्य है, लेकिन एक छोटा है: Array.prototype.spliceबनाम a1.splice:)
निकफ

जोड़ा सामान्य उद्देश्य सरणी सम्मिलन समारोह।
२१

.concatएक नया सरणी देता है, यह मौजूदा की तरह संशोधित नहीं करता है splice। होना चाहिएargs = args.concat(arrayToInsert);
निक

0
var a1 = [1,2,3,4,5];
var a2 = [21,22];

function injectAt(d, a1, a2) {
    for(var i=a1.length-1; i>=d; i--) {
        a1[i + a2.length] = a1[i];
    }
    for(var i=0; i<a2.length; i++) {
        a1[i+d] = a2[i];
    }
}

injectAt(2, a1, a2);

alert(a1);

0

यहाँ कोई विशेष चाल के साथ मेरा संस्करण है:

function insert_array(original_array, new_values, insert_index) {
    for (var i=0; i<new_values.length; i++) {
        original_array.splice((insert_index + i), 0, new_values[i]);
    }
    return original_array;
}

इस मामले में, प्रत्येक पुनरावृत्ति के लिए Insert_index वृद्धि के बजाय, यह केवल .reverse () new_values ​​सरणी के लिए सरल हो सकता है। बेशक, जब start_index शून्य या start_index - 1 है, तो इस समाधान की दक्षता खराब है, बिना किसी स्पष्ट छोरों के बस .concat () का उपयोग करने की तुलना में, या unshift () या पुश () `के साथ .apply()
एंथनी रटलेज

0

यदि आप एक नया बनाने के बिना एक और सरणी को एक सरणी में सम्मिलित करना चाहते हैं, तो सबसे आसान तरीका pushया तो उपयोग unshiftकरना हैapply

उदाहरण के लिए:

a1 = [1,2,3,4,5];
a2 = [21,22];

// Insert a1 at beginning of a2
a2.unshift.apply(a2,a1);
// Insert a1 at end of a2
a2.push.apply(a2,a1);

दोनों क्योंकि यह काम करता है pushऔर unshiftतर्क के परिवर्तनशील ले। एक बोनस, आप आसानी से चुन सकते हैं कि कौन सा ऐरे से अटैच करना है!


बस करके a1.concat(a2)या a2.concat(a1)मैंने आपके द्वारा सुझाए गए से कुछ आसान बना दिया है। हालाँकि, समस्या सरणी सीमाओं के बीच एक सरणी सम्मिलित कर रही है, विशेष रूप से शुरुआत या अंत में एक सरणी नहीं जोड़ रही है। ;-)
एंथनी रटलेज

0

जैसा कि एक अन्य सूत्र में बताया गया है, ऊपर दिए गए उत्तर बहुत बड़ी सरणियों (200K तत्वों) में काम नहीं करेंगे। ब्याह और मैनुअल पुश से जुड़े वैकल्पिक जवाब यहां देखें: https://stackoverflow.com/a/41465578/1038326

Array.prototype.spliceArray = function(index, insertedArray) {
    var postArray = this.splice(index);
    inPlacePush(this, insertedArray);
    inPlacePush(this, postArray);

    function inPlacePush(targetArray, pushedArray) {
  // Not using forEach for browser compatability
        var pushedArrayLength = pushedArray.length;
        for (var index = 0; index < pushedArrayLength; index++) {
           targetArray.push(pushedArray[index]);
       }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.