লুপের জন্য ব্রেক না করে অ্যারের মাধ্যমে লুপিং এবং আইটেমগুলি সরিয়ে ফেলা হচ্ছে


462

আমার কাছে লুপের জন্য নিম্নলিখিতগুলি রয়েছে এবং আমি যখন splice()কোনও আইটেমটি সরিয়ে ফেলার জন্য ব্যবহার করি, তখন আমি পাই যে 'সেকেন্ড' অপরিজ্ঞাত। এটি অপরিজ্ঞাত কিনা তা আমি চেক করতে পারি, তবে আমি মনে করি এটি করার জন্য আরও একটি মার্জিত উপায় আছে। ইচ্ছাটি হ'ল কোনও আইটেম মুছুন এবং চালিয়ে যান।

for (i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    Auction.auctions[i]['seconds'] --;
    if (auction.seconds < 0) { 
        Auction.auctions.splice(i, 1);
    }           
}

11
পিছনে পুনরাবৃত্তি এবং দৈর্ঘ্য সামঞ্জস্য করা ছাড়াও, আপনি কেবল নিজের সদস্যদের নতুন অ্যারেতে রাখতে পারেন।
রবজি ২

2
এর Auction.auctions[i]['seconds']--বদলে বলো কেন auction.seconds--?
ডন হ্যাচ

আপনি সম্ভবত পূর্বনির্ধারিত ফাংশন সন্ধান করতে চান। শিফট ();
রাকু

উত্তর:


856

অ্যারে যখন আপনি একটি করবেন তখন পুনরায় সূচীকরণ করা হচ্ছে .splice(), যার অর্থ একটি অপসারণের পরে আপনি কোনও সূচকে এড়িয়ে যাবেন এবং আপনার ক্যাশেগুলি .lengthঅপ্রচলিত।

এটির সমাধানের জন্য, আপনাকে হয় iক এর পরে হ্রাস করতে হবে .splice(), বা কেবল বিপরীতে পুনরাবৃত্তি করতে হবে ...

var i = Auction.auctions.length
while (i--) {
    ...
    if (...) { 
        Auction.auctions.splice(i, 1);
    } 
}

এইভাবে পুনরায় সূচীকরণটি পুনরাবৃত্তির পরবর্তী আইটেমকে প্রভাবিত করে না, কারণ সূচকগুলি কেবল বিন্দুর বর্তমান বিন্দু থেকে অ্যারের শেষ পর্যন্ত আইটেমগুলিকে প্রভাবিত করে এবং পুনরাবৃত্তির পরবর্তী আইটেমটি বর্তমান পয়েন্টের চেয়ে কম হয়।


151

এটি একটি খুব সাধারণ সমস্যা। সমাধানটি পিছনের দিকে লুপ করা:

for (var i = Auction.auctions.length - 1; i >= 0; i--) {
    Auction.auctions[i].seconds--;
    if (Auction.auctions[i].seconds < 0) { 
        Auction.auctions.splice(i, 1);
    }
}

আপনি এগুলি শেষের দিকে পপ করে যাচ্ছেন কিনা তা বিবেচ্য নয় কারণ সূচকগুলি পিছনের দিকে যাওয়ার সাথে সাথে সংরক্ষণ করা হবে।


47

প্রতিটি শুরুতে ঠিক পরিবর্তে লুপের মাধ্যমে দৈর্ঘ্যটি পুনরায় গণনা করুন, যেমন:

for (i = 0; i < Auction.auctions.length; i++) {
      auction = Auction.auctions[i];
      Auction.auctions[i]['seconds'] --;
      if (auction.seconds < 0) { 
          Auction.auctions.splice(i, 1);
          i--; //decrement
      }
}

এইভাবে আপনি সীমা অতিক্রম করবেন না।

সম্পাদনা: যদি বিবৃতিতে একটি হ্রাস যুক্ত করা হয়।


32

যদিও আপনার প্রশ্নটি অ্যারে থেকে উপাদানগুলি মুছে ফেলা হচ্ছে এবং উপাদানগুলি (অন্য কিছু প্রক্রিয়াকরণ ছাড়াও) দক্ষতার সাথে অপসারণ সম্পর্কে নয়, আমি মনে করি অনুরূপ পরিস্থিতিতে যদি একজনকে এটি পুনর্বিবেচনা করা উচিত।

এই পদ্ধতির অ্যালগরিদমিক জটিলতা O(n^2)স্প্লাইস ফাংশন এবং লুপের জন্য উভয় অ্যারেতে পুনরাবৃত্তি হয় (স্প্লাইস ফাংশন সবচেয়ে খারাপ ক্ষেত্রে অ্যারের সমস্ত উপাদানকে সরিয়ে দেয়)। পরিবর্তে আপনি কেবল প্রয়োজনীয় অ্যারেগুলিকে নতুন অ্যারেতে ঠেলাতে পারেন এবং তারপরে সেই অ্যারেটিকে পছন্দসই ভেরিয়েবলের (যা কেবলমাত্র পুনরাবৃত্তি হয়েছিল) তে নির্ধারণ করতে পারেন।

var newArray = [];
for (var i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    auction.seconds--;
    if (!auction.seconds < 0) { 
        newArray.push(auction);
    }
}
Auction.auctions = newArray;

ES2015 যেহেতু আমরা এগুলি Array.prototype.filterসমস্ত এক লাইনে ফিট করতে পারি :

Auction.auctions = Auction.auctions.filter(auction => --auction.seconds >= 0);


10

আপনি যদি ES6 + ব্যবহার করছেন - তবে কেবল অ্যারে.ফিল্টার পদ্ধতিটি ব্যবহার করবেন না কেন?

Auction.auctions = Auction.auctions.filter((auction) => {
  auction['seconds'] --;
  return (auction.seconds > 0)
})  

নোট করুন যে ফিল্টার পুনরাবৃত্তির সময় অ্যারে উপাদানটি পরিবর্তন করা কেবলমাত্র অবজেক্টের জন্য কাজ করে এবং আদিম মানের অ্যারের জন্য কাজ করবে না।


9

অ্যারে উপাদানগুলি হজম করার জন্য আরও একটি সহজ সমাধান:

while(Auction.auctions.length){
    // From first to last...
    var auction = Auction.auctions.shift();
    // From last to first...
    var auction = Auction.auctions.pop();

    // Do stuff with auction
}

8

স্প্লাইস এর সঠিক ব্যবহারের জন্য এখানে আরও একটি উদাহরণ। এই উদাহরণটি 'অ্যারে' থেকে 'অ্যাট্রিবিউট' সরিয়ে ফেলতে চলেছে।

for (var i = array.length; i--;) {
    if (array[i] === 'attribute') {
        array.splice(i, 1);
    }
}

7

যে লুপটিতে স্প্লাইস কোড রয়েছে তার কোড সহ এই অতি মৌলিক প্রশ্নের উত্তর দিয়েছেন এমন প্রত্যেক ব্যক্তির কাছে, যেটি ও (এন ) সময় চালিয়েছে, বা এই প্রশ্নটি পোস্ট হওয়ার সাত বছর পরে কে এই জাতীয় উত্তরটিকে সমর্থন করেছে: আপনার উচিত লজ্জিত হওয়া

এই সরল রৈখিক সময়ের সমস্যার জন্য এখানে একটি লিনিয়ার সময় সমাধান time

আমি যখন এই স্নিপেটটি চালাচ্ছি, যখন এন = 1 মিলিয়ন দিয়ে ফিল্টারইনপ্লেস () এ প্রতিটি কল আসে .013 থেকে .016 সেকেন্ডে। একটি চতুষ্কোণ সমাধান (যেমন স্বীকৃত উত্তর) মিলিয়ন বা তার বেশি সময় নিতে পারে।

// Remove from array every item such that !condition(item).
function filterInPlace(array, condition) {
   var iOut = 0;
   for (var i = 0; i < array.length; i++)
     if (condition(array[i]))
       array[iOut++] = array[i];
   array.length = iOut;
}

// Try it out.  A quadratic solution would take a very long time.
var n = 1*1000*1000;
console.log("constructing array...");
var Auction = {auctions: []};
for (var i = 0; i < n; ++i) {
  Auction.auctions.push({seconds:1});
  Auction.auctions.push({seconds:2});
  Auction.auctions.push({seconds:0});
}
console.log("array length should be "+(3*n)+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be "+(2*n)+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be "+n+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be 0: ", Auction.auctions.length)

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


আমি বুঝতে পারিনি আপনি কোনও অ্যারের দৈর্ঘ্য নির্ধারণ করতে পারবেন!
মাইকেল 20

আমি জানতাম না Array.splice(i,1)প্রতিবার একটি নতুন অ্যারে উদাহরণ তৈরি করবে। আমি খুব লজ্জিত।
19har

2
@ দেহার্ট হা, ভাল :-) আসলে এটি প্রতিবার একটি নতুন অ্যারে উদাহরণ তৈরি করে না; তবে এটিতে প্রতিটি আইটেমকেই বাম্প করতে হবে যার সূচকটি নীচের দিকে আমার চেয়ে বেশি, যা গড়ে এন / 2 বাচ্চা হয়।
ডন হ্যাচ

1

এই থ্রেডটিতে ইতিমধ্যে প্রচুর দুর্দান্ত উত্তর রয়েছে। তবে আমি যখন ES5 প্রসঙ্গে "অ্যারে থেকে nth উপাদান সরান" সমাধান করার চেষ্টা করেছি তখন আমার অভিজ্ঞতাটি ভাগ করে নিতে চেয়েছিলাম।

জাভাস্ক্রিপ্ট অ্যারেগুলির শুরু বা শেষ থেকে উপাদানগুলি যুক্ত / সরানোর জন্য বিভিন্ন পদ্ধতি রয়েছে। এইগুলো:

arr.push(ele) - To add element(s) at the end of the array 
arr.unshift(ele) - To add element(s) at the beginning of the array
arr.pop() - To remove last element from the array 
arr.shift() - To remove first element from the array 

মূলত উপরের পদ্ধতির কোনওটি অ্যারে থেকে নবম উপাদান সরানোর জন্য সরাসরি ব্যবহার করা যাবে না।

একটি বিষয় লক্ষণীয় যে এটি জাভা পুনরুক্তি ব্যবহারকারীর বিপরীতে যা পুনরাবৃত্তি করার সময় কোনও সংগ্রহের জন্য নবম উপাদানটি সরিয়ে ফেলা সম্ভব using

এটি মূলত আমাদের Array.spliceনবম উপাদানটি অপসারণের জন্য কেবল একটি অ্যারে পদ্ধতিতে ছেড়ে যায় (এই পদ্ধতিগুলির সাথে আপনি আরও কিছু করতে পারেন তবে এই প্রশ্নের প্রসঙ্গে আমি উপাদানগুলি অপসারণের দিকে মনোনিবেশ করছি):

Array.splice(index,1) - removes the element at the index 

মূল উত্তরটি (মন্তব্য সহ) থেকে অনুলিপি করা কোডটি এখানে:

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter else it would run into IndexOutBounds exception
{
  if (arr[i] === "four" || arr[i] === "two") {
    //splice modifies the original array
    arr.splice(i, 1); //never runs into IndexOutBounds exception 
    console.log("Element removed. arr: ");

  } else {
    console.log("Element not removed. arr: ");
  }
  console.log(arr);
}

আরেকটি লক্ষণীয় পদ্ধতি হ'ল Array.slice। তবে এই পদ্ধতির রিটার্ন টাইপ হ'ল সরানো উপাদান। এছাড়াও এটি মূল অ্যারে সংশোধন করে না। পরিবর্তিত কোড স্নিপেট নিম্নলিখিত হিসাবে:

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter 
{
  if (arr[i] === "four" || arr[i] === "two") {
    console.log("Element removed. arr: ");
    console.log(arr.slice(i, i + 1));
    console.log("Original array: ");
    console.log(arr);
  }
}

এটি বলার পরে, আমরা এখনও Array.sliceনীচের মতো প্রদর্শিত নবম উপাদানটি সরাতে ব্যবহার করতে পারি । তবে এটি অনেক বেশি কোড (অতএব অদক্ষ)

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter 
{
  if (arr[i] === "four" || arr[i] === "two") {
    console.log("Array after removal of ith element: ");
    arr = arr.slice(0, i).concat(arr.slice(i + 1));
    console.log(arr);
  }

}

Array.sliceপদ্ধতি a la redux কার্মিক প্রোগ্রামিং অপরিবর্তনীয়তা অর্জনে অত্যন্ত গুরুত্বপূর্ণ


নোট করুন যে আরও কোড কোনও কোডের দক্ষতার একটি পরিমাপ হওয়া উচিত নয়।
ক্যানো

0

লুপিংয়ের সময় একটি অ্যারেরকে নতুন অ্যারেতে রিলে করার চেষ্টা করুন:

var auctions = Auction.auctions;
var auctionIndex;
var auction;
var newAuctions = [];

for (
  auctionIndex = 0; 
  auctionIndex < Auction.auctions.length;
  auctionIndex++) {

  auction = auctions[auctionIndex];

  if (auction.seconds >= 0) { 
    newAuctions.push(
      auction);
  }    
}

Auction.auctions = newAuctions;

0

দুটি উদাহরণ যা কাজ করে:

(Example ONE)
// Remove from Listing the Items Checked in Checkbox for Delete
let temp_products_images = store.state.c_products.products_images
if (temp_products_images != null) {
    for (var l = temp_products_images.length; l--;) {
        // 'mark' is the checkbox field
        if (temp_products_images[l].mark == true) {
            store.state.c_products.products_images.splice(l,1);         // THIS WORKS
            // this.$delete(store.state.c_products.products_images,l);  // THIS ALSO WORKS
        }
    }
}

(Example TWO)
// Remove from Listing the Items Checked in Checkbox for Delete
let temp_products_images = store.state.c_products.products_images
if (temp_products_images != null) {
    let l = temp_products_images.length
    while (l--)
    {
        // 'mark' is the checkbox field
        if (temp_products_images[l].mark == true) {
            store.state.c_products.products_images.splice(l,1);         // THIS WORKS
            // this.$delete(store.state.c_products.products_images,l);  // THIS ALSO WORKS
        }
    }
}

0

একবার চেষ্টা করে দেখুন

RemoveItems.forEach((i, j) => {
    OriginalItems.splice((i - j), 1);
});

-2
for (i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    Auction.auctions[i]['seconds'] --;
    if (auction.seconds < 0) {
        Auction.auctions.splice(i, 1);
        i--;
        len--;
    }
}

7
একটি উত্তরের উত্তরটি সর্বদা কেবল ওপি-র জন্যই নয়, ভবিষ্যতে এসও-তে আগত দর্শকদের জন্য কী করা হয়েছিল এবং কেন এটি এমনভাবে করা হয়েছিল তার একটি ব্যাখ্যা সবসময় থাকবে।
বি 001 ᛦ

-2

আপনি কেবল দেখতে এবং ব্যবহার করতে পারেন shift()


3
এই পদ্ধতিটি ব্যবহার করে দয়া করে একটি উদাহরণ যুক্ত করুন।
ইভান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.