जावास्क्रिप्ट / jQuery में सरणी से कई तत्व निकालें


117

मेरे पास दो ऐरे हैं। पहले सरणी में कुछ मान होते हैं जबकि दूसरे सरणी में उन मानों के सूचक होते हैं जिन्हें पहले सरणी से हटाया जाना चाहिए। उदाहरण के लिए:

var valuesArr = new Array("v1","v2","v3","v4","v5");   
var removeValFromIndex = new Array(0,2,4);

मैं सूचकांक में मूल्यों वर्तमान निकालना चाहते 0,2,4से valuesArr। मुझे लगा कि देशी spliceतरीका मदद कर सकता है इसलिए मैं साथ आया:

$.each(removeValFromIndex,function(index,value){
    valuesArr.splice(value,1);
});

लेकिन यह काम नहीं किया क्योंकि प्रत्येक के बाद splice, मूल्यों के सूचकांक valuesArrअलग थे। मैं एक अस्थायी सरणी का उपयोग करके और दूसरे सरणी में सभी मानों की प्रतिलिपि बनाकर इस समस्या को हल कर सकता हूं, लेकिन मैं सोच रहा था कि क्या कोई देशी तरीके हैं जिनसे हम कई सूचकांकों को पारित कर सकते हैं जिन पर किसी सरणी से मानों को निकालना है।

मैं एक jQuery समाधान पसंद करेंगे। (निश्चित नहीं कि मैं grepयहाँ उपयोग कर सकता हूँ )

जवाबों:


256

हमेशा सादा पुराना forलूप होता है:

var valuesArr = ["v1","v2","v3","v4","v5"],
    removeValFromIndex = [0,2,4];    

for (var i = removeValFromIndex.length -1; i >= 0; i--)
   valuesArr.splice(removeValFromIndex[i],1);

removeValFromIndexरिवर्स ऑर्डर के माध्यम से जाओ और आप .splice()अभी तक हटाए जाने वाली वस्तुओं के अनुक्रमित को गड़बड़ाने के बिना कर सकते हैं ।

ऊपर ध्यान दें मैंने दो ऐरे को घोषित करने के लिए वर्ग कोष्ठक के साथ सरणी-शाब्दिक वाक्यविन्यास का उपयोग किया है। यह अनुशंसित सिंटैक्स है क्योंकि new Array()उपयोग संभावित रूप से भ्रामक है, यह इस बात पर निर्भर करता है कि आप कितने मापदंडों से गुजरते हैं, इस पर निर्भर करता है।

संपादित करें : बस अनुक्रमणिका के सरणी के बारे में एक और उत्तर पर आपकी टिप्पणी को देखा, जो जरूरी नहीं कि किसी विशेष क्रम में हो। यदि ऐसा हो तो शुरू करने से पहले इसे केवल अवरोही क्रम में क्रमबद्ध करें:

removeValFromIndex.sort(function(a,b){ return b - a; });

और जो कुछ भी लूपिंग / $.each()/ आदि विधि आपको पसंद है उसका अनुसरण करें ।


1
सूचकांक में गड़बड़ी नहीं है
मुहम्मद उमर

5
@ मुहम्मदउमर - नहीं, अगर आप इसे सही तरीके से नहीं करते हैं, तो वही है जो मेरा उत्तर बताता है।
nnnnnn 19

5
रिवर्स ऑर्डर जागरूकता के लिए धन्यवाद।
डैनियल नलबाक

2
+1, मुझे नहीं पता था कि मुझे अलग-अलग क्रम में ब्याह करना था, हालांकि forEach का उपयोग करने के बजाय, मेरा दृष्टिकोण उपयोग कर रहा है$.each(rvm.reverse(), function(e, i ) {})
लुइस स्टेनली जोवेल

1
यह केवल तभी काम करेगा जब removeValFromIndex आरोही क्रम में क्रमबद्ध हो
कुणाल बुरंगी

24

यहाँ एक है कि मैं जब नहीं दर्ज कराने के साथ प्रयोग कर रहा हूँ / अंडरस्कोर:

while(IndexesToBeRemoved.length) {
    elements.splice(IndexesToBeRemoved.pop(), 1);
}

सुरुचिपूर्ण समाधान! पहले तो मुझे लगा कि यह काम नहीं करेगा क्योंकि मैंने सोचा था कि हर बार जब आप कॉल sliceकरते हैं तो आपको हटाए जाने वाले इंडेक्स को फिर से गणना करना होगा (-1 ऑन IndexestoBeRemoved), लेकिन यह वास्तव में काम करता है!
रेनाटो गामा

2
बहुत चालाक
फ़रज़ाद YZ

11
यह समाधान काम करता है यदि केवल IndexesToBeRemovedसरणी आरोही द्वारा क्रमबद्ध है।
xfg

उन सूचकांकों को पहले विभाजन के बाद अमान्य कर दिया जाएगा।
शिंज़ौ

@ शिनज़ौ - नहीं तो IndexesToBeRemovedक्रमबद्ध (आरोही) है।
nnnnnn

18

नहीं in-placeलेकिन उपयोग किया जा सकता grepहै और inArrayके कार्यों jQuery

var arr = $.grep(valuesArr, function(n, i) {
    return $.inArray(i, removeValFromIndex) ==-1;
});

alert(arr);//arr contains V2, V4

इस बेला की जाँच करें


यदि आप अभी कहते हैं तो यह (लगभग पर्याप्त) अंदर जगह होगीvaluesArr = $.grep(...);
nnnnnn

1
@nnnnnn हा हा हा मैं एक बैठक के लिए जा रहा था (आप जानते हैं कि वे आपको इतना उत्पादक बनाते हैं) इसलिए ज्यादा प्रयोग नहीं किया।
TheVillageIdiot

1
@ cept0 डाउनवोट क्यों? ओपी ने jQuery समाधान के लिए कहा।
Ste77

आपको बहुत - बहुत धन्यवाद! @ विलविलियोट
इकोवो

jsfiddler - त्रुटि 404. हमें वास्तव में खेद है, लेकिन ऐसा कोई पृष्ठ नहीं है।
ऐश

17

मेरा सुझाव है कि आप Array.prototype.filter का उपयोग करें

var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
     return removeValFrom.indexOf(index) == -1;
})

फ़िल्टर के अंदर indexOf ... इष्टतम नहीं
अल्वारो जोआओ


महान! अब मैं सो सकता हूँ :)
फ़र्मांशी

7
function filtermethod(element, index, array) {  
    return removeValFromIndex.find(index)
}  
var result = valuesArr.filter(filtermethod);

MDN संदर्भ यहाँ है


@ riship89 फिडेल नीचे है
mate64

@ कर्ण: फिडल नीचे है
ऋषिपोह

1
कृपया ध्यान दें कि लेखन के समय (जून 2014), Array.prototype.find वर्तमान ES6 ड्राफ्ट का हिस्सा है और केवल वर्तमान फ़ायरफ़ॉक्स
Olli K

6

शुद्ध जेएस में आप पीछे की ओर सरणी के माध्यम से लूप कर सकते हैं, इसलिए splice()लूप के बगल में तत्वों के सूचकांक को गड़बड़ नहीं करेंगे:

for (var i = arr.length - 1; i >= 0; i--) {
    if ( yuck(arr[i]) ) {
        arr.splice(i, 1);
    }
}

काम नहीं करता है yuck एक फ़ंक्शन नहीं है, इसलिए यह मान लिया गया है कि यह अवांछित तत्व अनुक्रमित का सूचकांक है, और उपयोग किए गए
yuck

5

O(n)समय के साथ उत्तर पोस्ट करना आवश्यक लगता है :)। स्प्लिस सॉल्यूशन के साथ समस्या यह है कि एरे का शाब्दिक रूप से एरे के कार्यान्वयन के कारण , प्रत्येक spliceकॉल में O(n)समय लगेगा। यह तब स्पष्ट होता है जब हम इस व्यवहार का फायदा उठाने के लिए एक उदाहरण तैयार करते हैं:

var n = 100
var xs = []
for(var i=0; i<n;i++)
  xs.push(i)
var is = []
for(var i=n/2-1; i>=0;i--)
  is.push(i)

यह बीच से शुरू होने वाले तत्वों को हटाता है, इसलिए प्रत्येक हटाने से जेएस इंजन को n/2तत्वों की प्रतिलिपि बनाने के लिए मजबूर किया जाता है , हमारे पास (n/2)^2कुल कार्य हैं जो कि द्विघात है।

ब्याह समाधान (संभालने isसे पहले ही ओवरहेड्स से छुटकारा पाने के घटते क्रम में हल हो जाता है) इस तरह से होता है:

for(var i=0; i<is.length; i++)
  xs.splice(is[i], 1)

हालांकि, एक रैखिक समय समाधान को लागू करना मुश्किल नहीं है, खरोंच से सरणी का फिर से निर्माण करके, एक मास्क का उपयोग करके देखें कि क्या हम तत्वों की नकल करते हैं या नहीं (सॉर्ट इस पर जोर देगा O(n)log(n))। निम्नलिखित एक ऐसा कार्यान्वयन है ( maskगति के लिए बूलियन उलटा नहीं है ):

var mask = new Array(xs.length)
for(var i=is.length - 1; i>=0; i--)
  mask[is[i]] = true
var offset = 0
for(var i=0; i<xs.length; i++){
  if(mask[i] === undefined){
    xs[offset] = xs[i]
    offset++
  }
}
xs.length = offset

मैंने इसे jsperf.com पर चलाया और यहां तक n=100कि ब्याह विधि पूरी तरह से 90% धीमी है। बड़े के लिए nयह अंतर बहुत अधिक होगा।


5

त्वरित ES6 एक लाइनर:

const valuesArr = new Array("v1","v2","v3","v4","v5");   
const removeValFromIndex = new Array(0,2,4);

const arrayWithValuesRemoved = valuesArr.filter((value, i) => removeValFromIndex.includes(i))

आपका कोड तेजी से करता है, तो आप कर चलाना चाहिए removeValFromIndexएक Set()और प्रयोग removeValFromIndex.hasके बजाय includes
बोरिस

5

फ़िल्टर और सेट का उपयोग करके एक सरल और कुशल (रैखिक जटिलता) समाधान :

const valuesArr = ['v1', 'v2', 'v3', 'v4', 'v5'];   
const removeValFromIndex = [0, 2, 4];

const indexSet = new Set(removeValFromIndex);

const arrayWithValuesRemoved = valuesArr.filter((value, i) => !indexSet.has(i));

console.log(arrayWithValuesRemoved);

उस कार्यान्वयन का महान लाभ यह है कि सेट लुकअप ऑपरेशन ( hasफ़ंक्शन) एक निरंतर समय लेता है, उदाहरण के लिए, नेवस के उत्तर की तुलना में तेज है।


@MichaelPaccione की मदद करने की खुशी :)
अल्बर्टो ट्रिनेडेड टावारेस

3

यह मेरे लिए अच्छी तरह से काम करता है और वस्तुओं की एक सरणी से हटाने पर भी काम करता है:

var array = [ 
    { id: 1, name: 'bob', faveColor: 'blue' }, 
    { id: 2, name: 'jane', faveColor: 'red' }, 
    { id: 3, name: 'sam', faveColor: 'blue' }
];

// remove people that like blue

array.filter(x => x.faveColor === 'blue').forEach(x => array.splice(array.indexOf(x), 1));

इसे लिखने के लिए एक छोटा और अधिक आकर्षक तरीका हो सकता है लेकिन यह काम नहीं करता है।


2

ES5 का उपयोग कर एक सरल समाधान। यह आजकल अधिकांश अनुप्रयोगों के लिए अधिक उपयुक्त लगता है, क्योंकि कई अब jQuery आदि पर भरोसा नहीं करना चाहते हैं।

जब हटाए जाने वाले अनुक्रमितों को आरोही क्रम में क्रमबद्ध किया जाता है:

var valuesArr = ["v1", "v2", "v3", "v4", "v5"];   
var removeValFromIndex = [0, 2, 4]; // ascending

removeValFromIndex.reverse().forEach(function(index) {
  valuesArr.splice(index, 1);
});

जब हटाए जाने वाले अनुक्रमित क्रमबद्ध नहीं होते हैं:

var valuesArr = ["v1", "v2", "v3", "v4", "v5"];   
var removeValFromIndex = [2, 4, 0];  // unsorted

removeValFromIndex.sort(function(a, b) { return b - a; }).forEach(function(index) {
  valuesArr.splice(index, 1);
});

1

के removeValFromIndexसाथ बदलकर आप अपना कोड सही कर सकते हैं removeValFromIndex.reverse()। यदि उस सरणी को आरोही क्रम का उपयोग करने की गारंटी नहीं है, तो आप इसके बजाय उपयोग कर सकते हैं removeValFromIndex.sort(function(a, b) { return b - a })


मुझे अच्छा लग रहा है - jsfiddle.net/mrtsherman/gDcFu/2 । यद्यपि यह यह सुनिश्चित करता है कि निष्कासन सूची क्रम में है।
म्रतशर्मन

@minopret: धन्यवाद, लेकिन यह केवल तभी काम करेगा जब अनुक्रमित removeValFromIndexआरोही क्रम में हों।
xyz


1

यदि आप अंडरस्कोर का उपयोग कर रहे हैं। जेएस , आप _.filter()अपनी समस्या को हल करने के लिए उपयोग कर सकते हैं ।

var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
var filteredArr = _.filter(valuesArr, function(item, index){
                  return !_.contains(removeValFromIndex, index);
                });

इसके अतिरिक्त, यदि आप अनुक्रमित के बजाय आइटम की सूची का उपयोग करके आइटम निकालने का प्रयास कर रहे हैं, तो आप बस उपयोग कर सकते हैं _.without(), जैसे:

var valuesArr = new Array("v1","v2","v3","v4","v5");
var filteredArr = _.without(valuesArr, "V1", "V3");

अब filteredArrहोना चाहिए["V2", "V4", "V5"]


कैसे अंडरस्कोर में लागू किया जाता है ... सावधान रहें यदि यह फ़िल्टर के अंदर indexOf के बराबर है ... इष्टतम नहीं है ...
अल्वारो जोआओ

1

फ़िल्टर + इंडेक्सऑफ़ (IE9 +):

function removeMany(array, indexes) {
  return array.filter(function(_, idx) {
    return indexes.indexOf(idx) === -1;
  });
}); 

या ES6 फ़िल्टर + ढूँढें (एज +) के साथ:

function removeMany(array, indexes = []) {
  return array.filter((_, idx) => indexes.indexOf(idx) === -1)
}

फ़िल्टर के अंदर indexOf ... इष्टतम नहीं
अल्वारो जोआओ


0

लागू की तरह लग रहा है कि तुम क्या देख रहे हो सकता है।
शायद ऐसा कुछ काम करेगा?

Array.prototype.splice.apply(valuesArray, removeValFromIndexes );

लेकिन .splice()विधि हटाने के लिए तत्वों की एक सूची की उम्मीद नहीं कर रही है, यह तत्व के एक एकल सूचकांक की उम्मीद कर रही है जिस पर हटाने के लिए तत्वों की संख्या के बाद निकालना शुरू करना है ...
nnnnnn

0

कई मदों या अद्वितीय आइटम के लिए:

मेरा सुझाव है कि आप Array.prototype.filter का उपयोग करें

यदि आप पहले से ही इंडेक्स जानते हैं, तो कभी भी indexOf का उपयोग न करें!

var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];

valuesArr = valuesArr.filter(function(value, index) {
     return removeValFrom.indexOf(index) == -1;
}); // BIG O(N*m) where N is length of valuesArr and m is length removeValFrom

करना:

Hashes के साथ ... Array.prototyp.map का उपयोग कर

  var valuesArr = ["v1","v2","v3","v4","v5"];
  var removeValFrom = {};
  ([0, 2, 4]).map(x=>removeValFrom[x]=1); //bild the hash.
  valuesArr = valuesArr.filter(function(value, index) {
      return removeValFrom[index] == 1;
  }); // BIG O(N) where N is valuesArr;

0
var valuesArr = new Array("v1","v2","v3","v4","v5");   
var removeValFromIndex = new Array(0,2,4);

console.log(valuesArr)
let arr2 = [];

for (let i = 0; i < valuesArr.length; i++){
  if (    //could also just imput this below instead of index value
    valuesArr[i] !== valuesArr[0] && // "v1" <--
    valuesArr[i] !== valuesArr[2] && // "v3" <--
    valuesArr[i] !== valuesArr[4]    // "v5" <--
  ){
    arr2.push(valuesArr[i]);
  }
}

console.log(arr2);

यह काम। हालाँकि, आप इस प्रक्रिया में एक नई सारणी बनाएंगे। यकीन नहीं है कि यदि आप चाहते हैं या नहीं, लेकिन तकनीकी रूप से यह एक सरणी होगी जिसमें केवल वे मान होंगे जो आप चाहते थे।


-1

आप कोशिश कर सकते हैं और उपयोग कर सकते हैं। delete array[index]यह तत्व को पूरी तरह से हटा नहीं देगा, बल्कि इसके लिए मूल्य निर्धारित करेगा undefined


धन्यवाद लेकिन मैं तत्वों को हटाना चाहता हूं।
xyz

-1

आप Setसरणी से निर्माण कर सकते हैं और फिर सेट से एक सरणी बना सकते हैं।

const array = [1, 1, 2, 3, 5, 5, 1];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Result: [1, 2, 3, 5]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.