মান অনুসারে অ্যারে অনুলিপি করুন


1744

জাভাস্ক্রিপ্টে একটি অ্যারের অন্য অ্যারে অনুলিপি করার সময়:

var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d');  //Now, arr1 = ['a','b','c','d']

আমি বুঝতে পেরেছি যে নতুন, স্বতন্ত্র অ্যারের পরিবর্তে arr2একই অ্যারেটিকে বোঝায় arr1। দুটি স্বতন্ত্র অ্যারে পেতে আমি কীভাবে অ্যারেটি অনুলিপি করতে পারি?


3
দেখে মনে হচ্ছে এটি বর্তমানে ক্রোম 53 এবং ফায়ারফক্স 48 এ রয়েছে আমাদের জন্য দুর্দান্ত পারফরম্যান্স রয়েছে sliceএবং spliceঅপারেশন এবং নতুন স্প্রেড অপারেটর রয়েছে এবং এর Array.fromঅনেক ধীর প্রয়োগ রয়েছে। লুক এ perfjs.fnfo
Pencroff



এই অ্যারের (এক যে আদিম স্ট্রিং রয়েছে) জন্য আপনি ব্যবহার করতে পারেন var arr2 = arr1.splice();গভীর অনুলিপির, কিন্তু এই কৌশল যদি কাজ না আপনার অ্যারের মধ্যে উপাদানের আক্ষরিক কাঠামো (অর্থাত উপস্থিত থাকবে []বা {}) অথবা প্রোটোটাইপ বস্তু (যেমন function () {}, newইত্যাদি)। আরও সমাধানের জন্য নীচে আমার উত্তর দেখুন।
tfmontague

16
এটি 2017, সুতরাং আপনি ES6 বৈশিষ্ট্যগুলি ব্যবহারের বিষয়ে বিবেচনা করতে পারেন: let arr2 = [...arr1]; বিকাশকারী.মোজিলা.আর.ইন.ইউএস
ডকস / ওয়েব /

উত্তর:


2700

এটা ব্যবহার কর:

var newArray = oldArray.slice();

মূলত, slice()অপারেশন অ্যারেটিকে ক্লোন করে এবং একটি নতুন অ্যারের রেফারেন্স দেয়।

এটিও নোট করুন:

রেফারেন্স, স্ট্রিং এবং সংখ্যাগুলির জন্য (এবং আসল অবজেক্ট নয়), slice()নতুন অ্যারেতে অবজেক্ট রেফারেন্সগুলি অনুলিপি করে। মূল এবং নতুন অ্যারে উভয়ই একই বস্তুকে বোঝায়। যদি কোনও রেফারেন্সযুক্ত অবজেক্ট পরিবর্তন হয় তবে পরিবর্তনগুলি নতুন এবং মূল উভয় অ্যারে দৃশ্যমান।

স্ট্রিং এবং সংখ্যার মতো পুরানোগুলি অপরিবর্তনীয়, তাই স্ট্রিং বা সংখ্যায় পরিবর্তন অসম্ভব।


9
কর্মক্ষমতা সম্পর্কে নিম্নোক্ত jscreen পরীক্ষাগুলি প্রকৃতপক্ষে দেখায় যে var arr2 = arr1.slice () var arr2 = arr1.concat () এর মতোই দ্রুত; জেএসপিফারফ: jsperf.com/copy-array-slice-vs-concat/5 এবং jsperf.com/copy-simple-arrayJsperf.com/array-copy/5 এর ফলাফল আমাকে পরীক্ষার কোডটি বৈধ কিনা তা নিয়ে আমি ভাবছি surprised
কোহেন

94
যদিও এটি ইতিমধ্যে এক টন upvotes পেয়েছে, এটি অন্যটির জন্য প্রাপ্য কারণ এটি জেএসে উল্লেখগুলি যথাযথভাবে বর্ণনা করে যা দুর্ভাগ্যক্রমে বিরল, এরকম।
ওয়েইন

34
@ গ্যাবারআইমির আপনি কি কেবল পাঠযোগ্যতার জন্য একটি পুরো লাইব্রেরি যুক্ত করবেন? সত্যি? আমি যদি কেবল পাঠযোগ্যতার জন্য উদ্বিগ্ন ছিলাম তবে আমি একটি মন্তব্য যুক্ত করব। দেখুন: var newArray = oldArray.slice (); // ক্লোন পুরানোআরে নতুনরেটে
ডুয়াদওয়াদ

12
@ গ্যাবারআইমারে আমি এটি পেয়েছি তবে আমার মতে একটি সম্পূর্ণ লাইব্রেরি অন্তর্ভুক্ত করে নির্দিষ্ট ইঞ্জিনিয়ারিং সমস্যার উত্তর দেওয়া সহায়ক নয়, এটি নকশা ফুলেছে। আমি বিকাশকারীরা এটি অনেক কিছু করতে দেখছি এবং তারপরে আপনি এমন একটি প্রকল্পের সমাপ্তি করবেন যা একটি একক ফাংশন লেখার পরিবর্তে পুরো ফ্রেমওয়ার্কটি অন্তর্ভুক্ত করে। যদিও শুধু আমার এমও,
দুদেওয়াদ

5
পাঠ শিখেছি: .slice()সাথে বিভ্রান্ত করবেন না .splice(), যা আপনাকে একটি খালি অ্যারে দেয়। বড় পার্থক্য.
ক্রেজিপাইটার

530

জাভাস্ক্রিপ্টে, গভীর কপির কৌশলগুলি অ্যারের উপাদানগুলির উপর নির্ভর করে। সেখানে শুরু করা যাক।

তিন ধরণের উপাদান

উপাদানগুলি হ'ল: আক্ষরিক মান, আক্ষরিক কাঠামো বা প্রোটোটাইপগুলি।

// Literal values (type1)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';

// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};

// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}`

এই উপাদানগুলি থেকে আমরা তিন ধরণের অ্যারে তৈরি করতে পারি।

// 1) Array of literal-values (boolean, number, string) 
const type1 = [true, 1, "true"];

// 2) Array of literal-structures (array, object)
const type2 = [[], {}];

// 3) Array of prototype-objects (function)
const type3 = [function () {}, function () {}];

গভীর অনুলিপি কৌশলগুলি তিনটি অ্যারের ধরণের উপর নির্ভর করে

অ্যারেতে থাকা উপাদানগুলির প্রকারের ভিত্তিতে আমরা গভীর কপি করতে বিভিন্ন কৌশল ব্যবহার করতে পারি।

উপাদান ধরণের দ্বারা জাভাস্ক্রিপ্ট গভীর অনুলিপি কৌশল

  • আক্ষরিক-মান (type1) অ্যারে , , , এবং কৌশল শুধুমাত্র আক্ষরিক মান (বুলিয়ান, সংখ্যা, এবং স্ট্রিং) সঙ্গে গভীর কপি অ্যারে ব্যবহার করা যেতে পারে; যেখানে স্প্রেড অপারেটরের সেরা পারফরম্যান্স রয়েছে ( https://measurethat.net/Benchmark/Show/4281/0/spread-array-performance-vs-slice-splice-concat )।
    [...myArray]myArray.splice(0)myArray.slice()myArray.concat()[...myArray]

  • আক্ষরিক-মান (type1) এবং আক্ষরিক-কাঠামো (type2) অ্যারে কৌশল গভীর কপি আক্ষরিক মান (বুলিয়ান, সংখ্যা, স্ট্রিং) এবং আক্ষরিক কাঠামো (অ্যারে, বস্তু) ব্যবহার করা যেতে পারে, কিন্তু বস্তু প্রোটোটাইপ না।
    JSON.parse(JSON.stringify(myArray))

  • সমস্ত অ্যারে (টাইপ 1, টাইপ 2, টাইপ 3)
    jQuery $.extend(myArray)কৌশলটি সমস্ত অ্যারে-প্রকারের গভীর-অনুলিপি করতে ব্যবহার করা যেতে পারে। ইন্ডসকোর এবং লো-ড্যাশের মতো লাইব্রেরিতে jQuery তে অনুরূপ গভীর-অনুলিপি ফাংশন সরবরাহ করা হয়েছে $.extend(), তবুও কম কর্মক্ষমতা রয়েছে। আরও আশ্চর্যের বিষয় হল, http://jsppha.com/js-deep-copy/15 কৌশলটির $.extend()চেয়ে উচ্চতর পারফরম্যান্স রয়েছে । এবং তৃতীয় পক্ষের লাইব্রেরিগুলি (jQuery এর মতো) থেকে দূরে সরে যাওয়া সেই বিকাশকারীদের জন্য, আপনি নিম্নলিখিত কাস্টম ফাংশনটি ব্যবহার করতে পারেন; যার performance। প্রসারিতের চেয়ে উচ্চতর কর্মক্ষমতা রয়েছে এবং সমস্ত অ্যারের ডিপ-কপি করে।JSON.parse(JSON.stringify(myArray))

function copy(aObject) {
  if (!aObject) {
    return aObject;
  }

  let v;
  let bObject = Array.isArray(aObject) ? [] : {};
  for (const k in aObject) {
    v = aObject[k];
    bObject[k] = (typeof v === "object") ? copy(v) : v;
  }

  return bObject;
}

সুতরাং প্রশ্নের উত্তর দিতে ...

প্রশ্ন

var arr1 = ['a','b','c'];
var arr2 = arr1;

আমি বুঝতে পেরেছি যে একটি নতুন, স্বতন্ত্র অ্যারের পরিবর্তে আর্ট 2 একই অ্যারেটিকে আরআর 1 হিসাবে বোঝায়। দুটি স্বতন্ত্র অ্যারে পেতে আমি কীভাবে অ্যারেটি অনুলিপি করতে পারি?

উত্তর

যেহেতু arr1আক্ষরিক মানগুলির একটি বিন্যাস (বুলিয়ান, সংখ্যা বা স্ট্রিং), আপনি উপরে আলোচিত যে কোনও গভীর অনুলিপি কৌশল ব্যবহার করতে পারেন, যেখানে স্প্রেড অপারেটর ...সর্বাধিক কর্মক্ষমতা রয়েছে।

// Highest performance for deep copying literal values
arr2 = [...arr1];

// Any of these techniques will deep copy literal values as well,
//   but with lower performance.
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above

1
এই পদ্ধতির অনেকগুলিই ভাল কাজ করে না। অ্যাসাইনমেন্ট অপারেটর ব্যবহারের অর্থ আপনাকে এর আসল আক্ষরিক মানটি পুনরায় স্বাক্ষর করতে হবে arr1। এটি খুব বিরল যে ঘটনাটি হতে চলেছে। ব্যবহার spliceobliterates arr1, যাতে একটি কপি এ সব নয়। JSONঅ্যারেতে থাকা কোনও মান যদি ফাংশন হয় বা প্রোটোটাইপ (যেমন একটি Date) থাকে তবে ব্যবহার ব্যর্থ হবে ।
ড্যানক্রাম্ব

স্প্লাইস ব্যবহার একটি আংশিক সমাধান। এটি JSON এর চেয়ে অনেক বেশি মামলায় ব্যর্থ হবে। স্প্লাইস স্ট্রিং এবং সংখ্যাগুলির একটি গভীর অনুলিপি তৈরি করে, যখন এটি মানগুলি সরিয়ে দেয় - কখনই বলেনি যে এটি কোনও অনুলিপি ফেরায়।
tfmontague

1
বিভাজন (0) কেন? এটি কি কাটা () না করা উচিত? আমি মনে করি এটি আসল অ্যারেটি সংশোধন না করার কথা, যা বিভক্ত হয়। @
জেমস

2
স্প্লাইস মূল অ্যারে (অগভীর অনুলিপি )গুলিতে পয়েন্টার তৈরি করবে। স্প্লাইস (0) অ্যারের উপাদানগুলির জন্য নতুন মেমরি (গভীর অনুলিপি) বরাদ্দ করবে যা সংখ্যা বা স্ট্রিং রয়েছে এবং অন্যান্য সমস্ত উপাদান ধরণের (অগভীর অনুলিপি) জন্য পয়েন্টার তৈরি করবে। স্প্লাইস ফাংশন-পদ্ধতিতে শূন্যের একটি শুরুর মানটি পাস করার পরে, এটি মূল অ্যারে থেকে কোনও উপাদানকে ছড়িয়ে দেবে না এবং তাই এটি এটিকে পরিবর্তন করে না।
tfmontague

1
আসলে, কেবলমাত্র এক ধরণের অ্যারে: "সামথিংস" এর একটি অ্যারে an [0,"1",{2:3},function random() {return 4;}, [[5,6,7],[8,9,10],[11,12,13]]]এবং অন্য কোনও অ্যারের মধ্যে কোনও পার্থক্য নেই ।
wizzwizz4

189

আপনি ...অ্যারে কপির জন্য অ্যারে স্প্রেড ব্যবহার করতে পারেন ।

const itemsCopy = [...items];

এছাড়াও যদি বিদ্যমানটি এটির অংশ হিসাবে একটি নতুন অ্যারে তৈরি করতে চান:

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];

অ্যারে স্প্রেডগুলি এখন সমস্ত বড় ব্রাউজারগুলিতে সমর্থিত তবে আপনার যদি পুরানো সমর্থন প্রয়োজন হয় তবে টাইপস্ক্রিপ্ট বা ব্যাবেল ব্যবহার করুন এবং ইএস 5 তে সংকলন করুন।

স্প্রেডে আরও তথ্য


1
এটি গভীর অনুলিপির জন্য কাজ করবে না। জাভাস্ক্রিপ্টে ডিপ ক্লোন একটি অ্যারে
এসএনএগ

151

কোন jQuery প্রয়োজন ... কাজের উদাহরণ

var arr2 = arr1.slice()

এটি অ্যারের প্রারম্ভের 0মধ্য দিয়ে অ্যারেটি শুরু অবস্থান থেকে অনুলিপি করে ।

এটি লক্ষণীয় যে এটি আদিম ধরণের (স্ট্রিং, সংখ্যা, ইত্যাদি) প্রত্যাশার মতো কাজ করবে এবং রেফারেন্স ধরণের জন্য প্রত্যাশিত আচরণটিও ব্যাখ্যা করবে ...

আপনার যদি রেফারেন্স প্রকারের অ্যারে থাকে তবে টাইপটি বলুন Object। অ্যারের অনুলিপি করা হবে , তবে উভয় অ্যারেতে একইগুলির উল্লেখ রয়েছে Object। সুতরাং এই ক্ষেত্রে দেখে মনে হবে অ্যারেটি আসলে অনুলিপি করা সত্ত্বেও রেফারেন্স দ্বারা অনুলিপি করা হয়েছে।


12
না এটি একটি গভীর অনুলিপি হবে না।
jondavidjohn

এটা চেষ্টা কর; var arr2 = JSON.stringify(arr1); arr2 = JSON.parse(arr2);
প্রদীপ 1991 সিংহ

2
এই উত্তর এবং গৃহীত উত্তরের মধ্যে পার্থক্য কী?
আইজাক পাক

আপনার প্রদত্ত উদাহরণের জন্য কনসোলে ত্রুটি পেয়ে "টাইপ এয়ারার: ​​উইন্ডো.এডএডভেন্ট কোনও ফাংশন নয়"
রবি শর্মা

72

একটি বিকল্প sliceহয় concat, যা 2 উপায়ে ব্যবহার করা যাবে। এর মধ্যে প্রথমটি সম্ভবত সম্ভবত আরও পাঠযোগ্য কারণ উদ্দেশ্যমূলক আচরণটি খুব স্পষ্ট:

var array2 = [].concat(array1);

দ্বিতীয় পদ্ধতিটি হ'ল:

var array2 = array1.concat();

কোহেন (মন্তব্যে) উল্লেখ করেছেন যে এই আধুনিক পদ্ধতিটির আরও ভাল পারফরম্যান্স রয়েছে

যেভাবে এটি কাজ করে তা হ'ল concatপদ্ধতিটি একটি নতুন অ্যারে তৈরি করে যা বস্তুটির উপাদানগুলির সমন্বয়ে তাকে আর্গুমেন্ট হিসাবে প্রেরিত কোনও অ্যারের উপাদান অনুসরণ করে followed সুতরাং যখন কোন যুক্তি পাস করা হয় না, এটি কেবল অ্যারের অনুলিপি করে।

লি পেনম্যান, মন্তব্যগুলিতেও উল্লেখ করেছেন যে যদি সুযোগ থাকে array1তবে undefinedআপনি খালি অ্যারেটি নিম্নরূপে ফিরিয়ে দিতে পারেন:

var array2 = [].concat(array1 || []);

অথবা, দ্বিতীয় পদ্ধতির জন্য:

var array2 = (array1 || []).concat();

উল্লেখ্য আপনার কাছে সঙ্গে এই কাজ করতে পারে slice: var array2 = (array1 || []).slice();


31
আসলে আপনি এটিও করতে পারেন: var অ্যারে 2 = অ্যারে 1.concat (); পারফরম্যান্স সম্পর্কিত এটি অনেক দ্রুত। (জেএসপিফারফ: jsperf.com/copy-somple-array এবং jsperf.com/copy-array-slice-vs-concat/5
কোহেন

5
এটি লক্ষণীয় যে অ্যারে 1 যদি একটি অ্যারে না থাকে তবে উদাহরণস্বরূপ [].concat(array1)ফিরে আসে [array1]যদি এটির অপরিজ্ঞাত আপনি পাবেন [undefined]। আমি মাঝে মাঝে করিvar array2 = [].concat(array1 || []);
লি পেনকম্যান

60

অনেক পদ্ধতির চেষ্টা করার পরেও আমি এটি করেছি:

var newArray = JSON.parse(JSON.stringify(orgArray));

এটি একটি নতুন গভীর অনুলিপি তৈরি করবে যা প্রথমটির সাথে সম্পর্কিত নয় (অগভীর অনুলিপি নয়)।

এছাড়াও এটি অবশ্যই ইভেন্ট এবং ফাংশনগুলি ক্লোন করবে না, তবে ভাল জিনিসটি আপনি এটি এক লাইনে করতে পারেন এবং এটি যে কোনও ধরণের অবজেক্ট (অ্যারে, স্ট্রিং, সংখ্যা, অবজেক্টস ...) এর জন্য ব্যবহার করা যেতে পারে)


4
এটি সেরা এক। আমি দীর্ঘদিন আগে একই পদ্ধতি ব্যবহার করেছি এবং মনে করি পুরানো স্কুল পুনরাবৃত্ত লুপগুলিতে আর কোনও জ্ঞান নেই
ভ্লাদিমির খারালাম্পপিদি

1
সচেতন থাকুন যে এই বিকল্পটি গ্রাফের মতো কাঠামোগুলি ভালভাবে পরিচালনা করতে পারে না: চক্রের উপস্থিতিতে ক্র্যাশ হয় এবং ভাগ করা রেফারেন্স সংরক্ষণ করে না।
রুবেন

1
এটি Dateপ্রোটোটাইপযুক্ত কোনও কিছুর মতো বা সত্যই ব্যর্থ হয় । এছাড়াও, undefinedএস এস এ রূপান্তরিত হন null
ড্যানক্রাম্ব

7
কেউ কি সিপিইউ এবং পাঠ্যকে সিরিয়ালকরণের মেমরির উভয়টিতেই স্থূল অদক্ষতা সম্পর্কে মন্তব্য করার মতো সাহসী নয় এবং তারপরে কোনও বস্তুর পিছনে পার্সিং করছেন?
লরেন্স ডল

3
এই সমাধানটি একমাত্র কাজ করে। স্লাইস () ব্যবহার করা আসলেই একটি জাল সমাধান।

20

সংখ্যা বা স্ট্রিংয়ের মতো সাধারণ ডেটা ধরণের সাথে কাজ করার সময় উল্লিখিত কয়েকটি পদ্ধতি ভাল কাজ করে তবে অ্যারেতে অন্য বস্তু থাকলে এই পদ্ধতিগুলি ব্যর্থ হয়। আমরা যখন কোনও অ্যারে থেকে অন্য অ্যারেতে পাস করার চেষ্টা করি তখন এটি রেফারেন্স হিসাবে পাস করা হয়, বস্তু নয়।

আপনার জাভাস্ক্রিপ্ট ফাইলে নিম্নলিখিত কোড যুক্ত করুন:

Object.prototype.clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (i in this) {
        if (i == 'clone') 
            continue;
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        } 
        else 
            newObj[i] = this[i]
    } return newObj;
};

এবং সহজভাবে ব্যবহার

var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()

এটা কাজ করবে।


2
আমি এই ভুল পান যখন আমি আমার পাতায় এই কোড যোগ করা 'Uncaught RangeError: সর্বাধিক কল স্ট্যাক আকারকে ছাড়িয়ে'
sawe

1
আমার ক্ষমাপ্রার্থী, এআর 1 ঘোষণা না করা হলে ক্রোমে এই ত্রুটি ঘটে। সুতরাং আমি উপরের কোডটি কপি-পেস্ট করেছি এবং আমি ত্রুটিটি পেয়েছি, তবে আমি যদি অ্যারে অ্যারি 1 ঘোষণা করি তবে আমি ত্রুটিটি পাই না। আপনি এরি 2 এর ঠিক উপরে এআর 1 ঘোষণা করে উত্তরটি উন্নত করতে পারেন, আমি দেখছি সেখানে 'আমাদের মধ্যে' বেশ কয়েকজন রয়েছেন যারা চিনতে পারেন নি যে আমাদের আরার 1 ঘোষণা করতে হয়েছিল (আংশিক কারণ যখন আমি যখন আপনার উত্তরটি মূল্যায়ন করছিলাম তখন আমি হুড়োহুড়ি করেছিলাম) এবং কিছু যে 'ঠিকঠাক কাজ করছে') প্রয়োজন
sawe

.slice()আপনার অ্যারেতে অবজেক্ট থাকলেও এখনও ঠিকঠাক কাজ করে
জেসন

7
@ জেসন কিন্তু অবজেক্টস এখনও একই অবজেক্টের দিকে ইশারা করছে তাই একটি পরিবর্তন করলে অন্যটির পরিবর্তন হবে। jsfiddle.net/k525g/1
স্যামুয়েল

দুর্দান্ত কোড। আমার একটি প্রশ্ন আছে, আমি আসলে এই অ্যারে 1 এর মতো অন্য অ্যারে = নতুন অ্যারে () এবং তারপরে ভের অ্যারে 2 = অ্যারে 1 এর মধ্যে একটি অ্যারের অনুলিপি করার চেষ্টা করেছি; যদি আমি আরআর 2 তে কিছু পরিবর্তন করি তবে পরিবর্তনটি এআর 1 এও ঘটে। তবে, আমি যদি আপনার তৈরি ক্লোন প্রোটোটাইপ ব্যবহার করি তবে এটি আসলে সেই অ্যারের সম্পূর্ণ নতুন উদাহরণ তৈরি করে বা অন্য কথায় এটি এটি অনুলিপি করে। তাহলে এটি কি ব্রাউজারের সমস্যা? বা জাভাস্ক্রিপ্ট ডিফল্টরূপে দুটি ভেরিয়েবল সেট করে পয়েন্টার ব্যবহারের সাথে অন্যকে নির্দেশ করে যখন কেউ var arr2 = arr1 করে এবং কেন পূর্ণসংখ্যের ভেরিয়েবলের সাথে ঘটে না? দেখতে jsfiddle.net/themhz/HbhtA
themhz


17

আমি ব্যক্তিগতভাবে মনে করি অ্যারে.ফ্রম একটি আরও পঠনযোগ্য সমাধান। যাইহোক, কেবল এর ব্রাউজার সমর্থন থেকে সাবধান থাকুন।

//clone
let x = [1,2,3];
let y = Array.from(x);

//deep clone
let clone = arr => Array.from(arr,item => Array.isArray(item) ? clone(item) : item);
let x = [1,[],[[]]];
let y = clone(x);

1
হ্যাঁ, এটি খুব পঠনযোগ্য। .slice()সমাধান সম্পূর্ণরূপে unintuitive হয়। এর জন্য ধন্যবাদ.
বানাগো

15

গুরুত্বপূর্ণ!

এখানে বেশিরভাগ উত্তর নির্দিষ্ট ক্ষেত্রে কাজ করে

যদি আপনি গভীর / নেস্টেড অবজেক্ট এবং প্রপস ব্যবহার ( ES6 ) সম্পর্কে চিন্তা করেন না:

let clonedArray = [...array]

তবে আপনি যদি ডিপ ক্লোন করতে চান তবে এর পরিবর্তে এটি ব্যবহার করুন:

let cloneArray = JSON.parse(JSON.stringify(array))


লড্যাশ ব্যবহারকারীদের জন্য:

let clonedArray = _.clone(array) ডকুমেন্টেশন

এবং

let clonedArray = _.cloneDeep(array) ডকুমেন্টেশন


11

আপনি যদি স্প্রেড অপারেটরটি ব্যবহার করে ECMAScript 6 এর পরিবেশে থাকেন তবে আপনি এটি এইভাবে করতে পারেন:

var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');

console.log(arr1)
console.log(arr2)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>


9

অ্যারে.স্লাইস () এর সমাধানে যুক্ত করা ; সচেতন হন যে আপনার যদি বহুমাত্রিক অ্যারে থাকে তবে সাব-অ্যারে রেফারেন্সগুলি দ্বারা অনুলিপি করা হবে। আপনি যা করতে পারেন তা হ'ল পৃথকভাবে প্রতিটি উপ-অ্যারে লুপ এবং টুকরো টুকরো করা

var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();

arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);

function arrCpy(arrSrc, arrDis){
 for(elm in arrSrc){
  arrDis.push(arrSrc[elm].slice());
}
}

var arr3=[];
arrCpy(arr,arr3);

arr3[1][1] = 77;

console.log(arr3[1][1]);
console.log(arr[1][1]);

একই জিনিস অবজেক্টের অ্যারেতে যায়, সেগুলি রেফারেন্স দ্বারা অনুলিপি করা হবে, আপনাকে সেগুলি ম্যানুয়ালি অনুলিপি করতে হবে


এই উত্তরটি পৃষ্ঠার শীর্ষের নিকটে একটি স্থানের দাবিদার! আমি বহুমাত্রিক সাব অ্যারে নিয়ে কাজ করছিলাম এবং কেন অভ্যন্তরীণ অ্যারেগুলি সর্বদা রেফ দ্বারা অনুলিপি করা হয় এবং ভাল দ্বারা নয় কেন তা অনুসরণ করতে পারি না। এই সহজ যুক্তি আমার সমস্যা সমাধান করেছে। আমি যদি আপনাকে সম্ভব হয় +100 দেবো!
ম্যাক

8

আদিম মানগুলি সর্বদা এর মান দ্বারা অনুলিপি হয় (অনুলিপি করা হয়)। যৌগিক মানগুলি রেফারেন্স দ্বারা পাস করা হয়।

তাহলে আমরা কীভাবে এই আরআরটি অনুলিপি করব?

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

ES6 এ একটি অ্যারে অনুলিপি করুন

let arrCopy = [...arr]; 

ES5 এ এন অ্যারে অনুলিপি করুন

let arrCopy = arr.slice(); 
let arrCopy = [].concat(arr);

`আসুন arrCopy = arr` মান দিয়ে কেন পার হচ্ছে না?

অবজেক্ট / অ্যারের মতো যৌগিক মানগুলিতে একের সাথে অন্যটির মধ্যে পরিবর্তন করা আলাদা হয়। কোপ্যান্ড মানগুলিতে অ্যাসাইন অপারেটর ব্যবহার করে আমরা কোনও বস্তুর রেফারেন্সটি পাস করি। আরার উপাদানগুলি সরিয়ে / যুক্ত করার সময় উভয় অ্যারের মানই পরিবর্তিত হয়।

ব্যতিক্রমসমূহ:

arrCopy[1] = 'adding new value this way will unreference';

আপনি যখন ভেরিয়েবলের জন্য একটি নতুন মান নির্ধারণ করেন, আপনি নিজেই রেফারেন্সটি পরিবর্তন করছেন এবং এটি আসল অবজেক্ট / অ্যারেটিকে প্রভাবিত করে না।

আরও পড়ুন


6

যেমনটি আমরা জাভাস্ক্রিপ্টে জানি অ্যারে এবং অবজেক্টগুলি রেফারেন্সের সাথে রয়েছে, তবে আমরা কীভাবে উপায়গুলি পরে মূল অ্যারেটি পরিবর্তন না করে কপি করতে পারি?

এটি করার কয়েকটি উপায় এখানে রয়েছে:

আপনার কোডে আমাদের এই অ্যারে রয়েছে তা কল্পনা করুন:

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

1) একটি ফাংশনে অ্যারের মাধ্যমে লুপিং এবং একটি নতুন অ্যারেটি ফিরে আসুন:

 function newArr(arr) {
      var i=0, res = [];
      while(i<arr.length){
       res.push(arr[i]);
        i++;
       }
   return res;
 }

২) স্লাইস পদ্ধতিটি ব্যবহার করে, স্লাইস অ্যারের অংশটি কাটানোর জন্য, এটি আপনার অ্যারের কিছু অংশ টুকরো টুকরো করে মূলটি স্পর্শ না করে স্লাইসে, যদি অ্যারের শুরু এবং শেষটি নির্দিষ্ট না করে, এটি পুরো টুকরো টুকরো করবে অ্যারে এবং মূলত অ্যারের একটি সম্পূর্ণ অনুলিপি তৈরি করুন, তাই আমরা সহজেই বলতে পারি:

var arr2 = arr.slice(); // make a copy of the original array

3) এছাড়াও যোগাযোগের পদ্ধতি, এটি দুটি অ্যারে মার্জ করার জন্য, তবে আমরা কেবল অ্যারেগুলির মধ্যে একটি নির্দিষ্ট করতে পারি এবং তারপরে এটি মূলত নতুন পরিচিত অ্যারেটিতে একটি অনুলিপি তৈরি করে:

var arr2 = arr.concat();

৪) এছাড়াও স্ট্রিংফায়েড এবং পার্স পদ্ধতিতে এটি প্রস্তাবিত নয়, তবে অ্যারে এবং অবজেক্টগুলি অনুলিপি করার সহজ উপায় হতে পারে:

var arr2 = JSON.parse(JSON.stringify(arr));

5) অ্যারে.ফর্ম পদ্ধতি থেকে, এটি বিভিন্নভাবে সমর্থিত নয়, ব্যবহারের আগে বিভিন্ন ব্রাউজারে সমর্থনটি পরীক্ষা করুন:

const arr2 = Array.from(arr);

6) ECMA6 উপায়, পুরোপুরি সমর্থিত নয়, তবে আপনি স্থানান্তর করতে চাইলে ব্যাবেলগুলি আপনাকে সহায়তা করতে পারে:

const arr2 = [...arr];

6
let a = [1,2,3];

অ্যারের অনুলিপি তৈরি করতে এখন আপনি নীচের যে কোনও একটি করতে পারেন।

let b = Array.from(a); 

অথবা

let b = [...a];

অথবা

let b = new Array(...a); 

অথবা

let b = a.slice(); 

অথবা

let b = a.map(e => e);

এখন, আমি যদি একটি পরিবর্তন করি,

a.push(5); 

তারপরে, একটি [1,2,3,5] কিন্তু খ এখনও [1,2,3] কারণ এর বিভিন্ন উল্লেখ রয়েছে।

কিন্তু আমি মনে করি, সর্বোপরি পদ্ধতিতে Array.from উত্তম এবং একটি অ্যারের কপি করতে প্রধানত প্রণীত।


1
কোনটি দ্রুততম?
মার্ক ফ্রেম


4

আমার বিশেষ ক্ষেত্রে আমার অ্যারেটি অক্ষত থাকবে তা নিশ্চিত করা দরকার তাই এটি আমার জন্য কাজ করেছিল:

// Empty array
arr1.length = 0;
// Add items from source array to target array
for (var i = 0; i < arr2.length; i++) {
    arr1.push(arr2[i]);
}

2
ঠিক একই জিনিসটি করে এমন কোনও ফাংশন কল করে আপনার কোডটিতে অস্পষ্টতা না যুক্ত করার জন্য +1, তবে কিছুটা স্পষ্টভাবে। টুকরো টুকরো টুকরো অধীনে আরও দক্ষ হতে পারে, কিন্তু যে কেউ কোডে কাজ করছেন, এটি আপনার উদ্দেশ্য দেখায়। প্লাস এটি পরে অপ্টিমাইজ করা সহজ করে তোলে, যদি আপনি চান (উদাহরণস্বরূপ) আপনি কী অনুলিপি করছেন তা ফিল্টার করুন। নোট করুন তবে এটি গভীর অনুলিপি পরিচালনা করে না এবং একই অভ্যন্তরীণ বস্তুগুলি রেফারেন্স সহ নতুন অ্যারেতে পাঠানো হবে। এটি আপনি যা করতে চান তা হতে পারে, এটি নাও পারে।
unsynchronized

4

বহুমাত্রিক অ্যারে / অবজেক্টের অনুলিপি তৈরি করুন:

function deepCopy(obj) {
   if (Object.prototype.toString.call(obj) === '[object Array]') {
      var out = [], i = 0, len = obj.length;
      for ( ; i < len; i++ ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   if (typeof obj === 'object') {
      var out = {}, i;
      for ( i in obj ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   return obj;
}

এই ফাংশনটির জন্য জেমস প্যাডলসিকে ধন্যবাদ।

সূত্র: এখানে


3

এবং, অভিনব কৌশল ব্যবহার করার প্রয়োজন নেই। আপনাকে যা করতে হবে তা হ'ল এটি করে আরআর 1 এর অনুলিপি তৈরি করুন।

var arr2 = new Array(arr1);

এখন arr1এবং arr2পৃথক স্ট্যাকগুলিতে দুটি পৃথক অ্যারে পরিবর্তনশীল। Jsfiddle এ দেখুন


এটি অ্যারে অনুলিপি করে না এটি একটি উপাদান সহ একটি অ্যারে তৈরি করে যা মূল (অর্থাত var arr2 = [arr1];) উল্লেখ করে ।
তীমথিয় 3003

3

যখন আমরা অ্যাসাইনমেন্ট অপারেটর ( =) ব্যবহার করে একটি অ্যারে অনুলিপি করতে চাই তখন এটি অনুলিপি তৈরি করে না এটি কেবল অ্যারের পয়েন্টার / রেফারেন্সটি অনুলিপি করে। উদাহরণ স্বরূপ:

const oldArr = [1,2,3];

const newArr = oldArr;  // now oldArr points to the same place in memory 

console.log(oldArr === newArr);  // Points to the same place in memory thus is true

const copy = [1,2,3];

console.log(copy === newArr);  // Doesn't point to the same place in memory and thus is false

প্রায়শই আমরা যখন ডেটা রূপান্তর করি তখন আমরা আমাদের প্রাথমিক ডেটাস্ট্রাকচার (যেমন অ্যারে) অক্ষত রাখতে চাই। আমরা আমাদের অ্যারের একটি সঠিক অনুলিপি তৈরি করে এটি করি যাতে প্রাথমিকটি অক্ষত থাকা অবস্থায় এইটিকে রূপান্তর করা যায়।

একটি অ্যারে অনুলিপি করার উপায়:

const oldArr = [1,2,3];

// Uses the spread operator to spread out old values into the new array literal
const newArr1 = [...oldArr];

// Slice with no arguments returns the newly copied Array
const newArr2 = oldArr.slice();

// Map applies the callback to every element in the array and returns a new array
const newArr3 = oldArr.map((el) => el);

// Concat is used to merge arrays and returns a new array. Concat with no args copies an array
const newArr4 = oldArr.concat();

// Object.assign can be used to transfer all the properties into a new array literal
const newArr5 = Object.assign([], oldArr);

// Creating via the Array constructor using the new keyword
const newArr6 = new Array(...oldArr);

// For loop
function clone(base) {
	const newArray = [];
    for(let i= 0; i < base.length; i++) {
	    newArray[i] = base[i];
	}
	return newArray;
}

const newArr7 = clone(oldArr);

console.log(newArr1, newArr2, newArr3, newArr4, newArr5, newArr6, newArr7);

অ্যারে বা অবজেক্টগুলি বাসা বাঁধলে সাবধান !:

অ্যারে নেস্ট করা হলে মানগুলি রেফারেন্স দ্বারা অনুলিপি করা হয়। এটি কীভাবে সমস্যার দিকে পরিচালিত করতে পারে তার উদাহরণ এখানে রয়েছে:

let arr1 = [1,2,[1,2,3]]

let arr2 = [...arr1];

arr2[2][0] = 5;  // we change arr2

console.log(arr1);  // arr1 is also changed because the array inside arr1 was copied by reference

সুতরাং আপনি যখন অনুলিপি করতে চান আপনার অ্যারের ভিতরে অবজেক্ট বা অ্যারে রয়েছে তখন এই পদ্ধতিগুলি ব্যবহার করবেন না। অর্থাত্ আদিমদের অ্যারেতে এই পদ্ধতিগুলি ব্যবহার করুন।

আপনি যদি জাভাস্ক্রিপ্ট অ্যারে ব্যবহারের JSON.parseসাথে ডিপ ক্লোন করতে চান তবে এর JSON.stringifyমতো:

let arr1 = [1,2,[1,2,3]]

let arr2 = JSON.parse(JSON.stringify(arr1)) ;

arr2[2][0] = 5;

console.log(arr1);  // now I'm not modified because I'm a deep clone

অনুলিপি সম্পাদন:

আমরা কোনটি সর্বোত্তম পারফরম্যান্সের জন্য বেছে নিই। দেখা যাচ্ছে যে সবচেয়ে ভার্বোজ পদ্ধতিতে লুপটির forসর্বোচ্চ কর্মক্ষমতা রয়েছে। forসত্যই সিপিইউ নিবিড় অনুলিপি করার জন্য লুপটি ব্যবহার করুন (বড় / অনেকগুলি অ্যারে)।

এর পরে .slice()পদ্ধতিটিতে শালীন পারফরম্যান্সও রয়েছে এবং প্রোগ্রামার বাস্তবায়নের পক্ষে কম ভার্জোজ এবং সহজ। আমি .slice()আপনার দৈনন্দিন অ্যারেগুলি অনুলিপি করার জন্য ব্যবহার করার পরামর্শ দিচ্ছি যা খুব সিপিইউ নিবিড় নয়। JSON.parse(JSON.stringify(arr))যদি কোনও গভীর ক্লোন প্রয়োজন হয় না এবং কার্য সম্পাদন কোনও সমস্যা হয় তবে (প্রচুর ওভারহেড) ব্যবহার এড়িয়ে চলুন ।

উত্স কর্মক্ষমতা পরীক্ষা


3

যদি আপনার অ্যারেতে প্রিমিটিভ ডেটা টাইপের যেমন ইন্ট, চর, বা স্ট্রিং ইত্যাদি উপাদান রয়েছে তবে আপনি সেই পদ্ধতিগুলির মধ্যে একটির ব্যবহার করতে পারেন যা মূল অ্যারের অনুলিপি যেমন .স্লাইস () বা। ম্যাপ () বা স্প্রেড অপারেটর ( ES6 কে ধন্যবাদ)।

new_array = old_array.slice()

অথবা

new_array = old_array.map((elem) => elem)

অথবা

const new_array = new Array(...old_array);

কিন্তু যদি আপনার অ্যারের রয়েছে জটিল উপাদান যেমন বস্তু (বা অ্যারে) অথবা এমন আরো অনেক নেস্টেড বস্তু , তারপর, আপনি কি ভেতরের শেষ স্তর অন্য রেফারেন্স শীর্ষ পর্যায় থেকে সব উপাদান একটি কপি তৈরি করছেন করতে হবে অবজেক্ট ব্যবহার করা হবে এবং এর অর্থ নতুন_রেরে অবজেক্ট_সিলিমেটির মানগুলি পরিবর্তন করা এখনও পুরানো_আরেকে প্রভাবিত করবে। আপনি প্রতিটি স্তরে অনুলিপি করার এই পদ্ধতিটিকে পুরানো_রেয়ার একটি ডিপ কপি তৈরি হিসাবে কল করতে পারেন ।

গভীর অনুলিপি করার জন্য, আপনি প্রতিটি স্তরের তথ্যের ধরণের উপর নির্ভর করে আদিম উপাত্ত ধরণের জন্য উপরে বর্ণিত পদ্ধতিগুলি ব্যবহার করতে পারেন বা বেশি কাজ না করে গভীর কপি তৈরির জন্য আপনি এই ব্যয়বহুল পদ্ধতিটি (নীচে উল্লিখিত) ব্যবহার করতে পারেন ।

var new_array = JSON.parse(JSON.stringify(old_array));

আপনার প্রয়োজনীয়তার উপর নির্ভর করে আপনি এখানে ব্যবহার করতে পারেন এমন আরও অনেক পদ্ধতি রয়েছে। আমি শুধু কি হবে যখন আমরা অন্য একটি বিন্যাস অনুলিপি করতে চেষ্টা একটি সাধারণ ধারণা দেবার জন্য যারা কিছু উল্লেখ করেছি মান


অনেক ধন্যবাদ, আপনার উত্তরটি কেবলমাত্র আমার দৃশ্যের জন্যই কাজ করেছিলেন
অ্যালবার্ট শ

2

আপনি যদি কোনও বস্তু বা অ্যারের একটি নতুন অনুলিপি তৈরি করতে চান তবে আপনাকে অবশ্যই স্পষ্টভাবে অবজেক্টের বৈশিষ্ট্য বা অ্যারের উপাদানগুলি অনুলিপি করতে হবে, উদাহরণস্বরূপ:

var arr1 = ['a','b','c'];
var arr2 = [];

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

অপরিবর্তনীয় আদিম মান এবং পরিবর্তনীয় অবজেক্ট রেফারেন্স সম্পর্কে আপনি গুগলে আরও তথ্য সন্ধান করতে পারেন।


1
আপনাকে অ্যারের বস্তুর বৈশিষ্ট্যগুলি স্পষ্টভাবে অনুলিপি করতে হবে না। চটিউই মালেকের উত্তর দেখুন।
ম্যাগনে



2

এখানে অনুলিপি করার আরও কয়েকটি উপায় রয়েছে:

const array = [1,2,3,4];

const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );


2

আপনি এর সহজতম স্প্রেড অপারেটারের সাথে ES6 ব্যবহার করতে পারেন।

arr2 = [...arr1];

সীমাবদ্ধতা রয়েছে .c


2

দ্রুত উদাহরণ:

  1. অ্যারের উপাদানগুলি আদিম ধরণের হলে (স্ট্রিং, সংখ্যা ইত্যাদি) are

var arr1 = ['a','b','c'];
// arr1 and arr2 are independent and primitive elements are stored in 
// different places in the memory
var arr2 = arr1.slice(); 
arr2.push('d');
console.log(arr1); // [ 'a', 'b', 'c' ]
console.log(arr2); // [ 'a', 'b', 'c', 'd' ]

  1. অ্যারের উপাদানগুলি যদি বস্তুর আক্ষরিক হয় তবে অন্য অ্যারে ({}, [])

var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
// arr1 and arr2 are independent and reference's/addresses are stored in different
// places in the memory. But those reference's/addresses points to some common place
// in the memory.
var arr2 = arr1.slice(); 
arr2.pop();      // OK - don't affect arr1 bcos only the address in the arr2 is
                 // deleted not the data pointed by that address
arr2[0].x = 'z'; // not OK - affect arr1 bcos changes made in the common area 
                 // pointed by the addresses in both arr1 and arr2
arr2[1][0] = 9;	 // not OK - same above reason

console.log(arr1); // [ { x: 'z', y: 'b' }, [ 9, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]

  1. 2 এর সমাধান : উপাদান দ্বারা উপাদান দ্বারা গভীর অনুলিপি

var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
arr2 = JSON.parse(JSON.stringify(arr1));
arr2.pop();	  // OK - don't affect arr1
arr2[0].x = 'z';  // OK - don't affect arr1
arr2[1][0] = 9;	  // OK - don't affect arr1

console.log(arr1); // [ { x: 'a', y: 'b' }, [ 1, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]


1

এখানে একটি বৈকল্পিক:

var arr1=['a', 'b', 'c'];
var arr2=eval(arr1.toSource());
arr2.push('d');
console.log('arr1: '+arr1+'\narr2: '+arr2);
/*
 *  arr1: a,b,c
 *  arr2: a,b,c,d
 */

না এই ধরনের একটি খারাপ ধারণা, যদিও আমি ভাল ব্যবহার করতে চাই তাদেরকে JSON stringify Eval পরিবর্তে / পার্স, এবং এখনও অন্য jsPerf তুলনা ভাল চেক আউট করতে, এছাড়াও নোট হবে toSourceমান নয় এবং উদাহরণস্বরূপ Chrome এ কাজ করবে না।
dmi3y

1

নতুনভাবে চালু হয়েছে Array.from, তবে দুর্ভাগ্যক্রমে, এই লেখার সময় হিসাবে এটি কেবল সাম্প্রতিক ফায়ারফক্স সংস্করণগুলিতে সমর্থিত (32 এবং এর বেশি)। এটি সহজভাবে নিম্নলিখিত হিসাবে ব্যবহার করা যেতে পারে:

var arr1 = [1, 2, 3];
console.log(Array.from(arr1)); // Logs: [1, 2, 3]

তথ্যসূত্র: এখানে

বা Array.prototype.mapএকটি পরিচয় ফাংশন ব্যবহার করা যেতে পারে:

function identity(param)
{
    return param;
}

var arr1 = [1, 2, 3],
    clone = arr1.map(identity);

তথ্যসূত্র: এখানে


উল্লেখ করার জন্য +1 Array.from, যা এখন ইন্টারনেট এক্সপ্লোরার ( উত্স ) ব্যতীত সমস্ত বড় ব্রাউজারগুলিতে সমর্থিত । ।
মিগথোমাস 99

সচেতন থাকুন Array.fromডেটা রূপান্তরিত করবে, গভীর অনুলিপি / গভীর ক্লোনিং সরবরাহ করে না।
সুধনসু চৌধারি

1

ES6 অ্যারে অবজেক্ট যুক্ত রয়েছে For

cloneArray(arr) {
    return arr.map(x => ({ ...x }));
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.