किसी सूची से मान के सभी आवृत्तियों को निकालें?


377

पायथन remove()में एक सूची में मूल्य की पहली घटना को हटा देगा।

किसी सूची से मूल्य की सभी घटनाओं को कैसे हटाया जाए ?

यह मेरे मन में है:

>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]

जवाबों:


505

कार्यात्मक दृष्टिकोण:

अजगर 3.x

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]

या

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]

अजगर 2.x

>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]

120
फ़िल्टर + लैम्ब्डा पर सूची समझ का उपयोग करें; पूर्व आमतौर पर अधिक कुशल के अलावा अधिक पठनीय है।
हबनबीत

17
s / आम तौर पर / आम तौर पर जा रहा है /
habnabit

99
हबनेट के सुझाव के लिए कोड इस तरह दिखता है:[y for y in x if y != 2]
coredumperror

8
मैं इस समाधान को सबसे अच्छा नहीं कहूंगा। कोड के माध्यम से स्किमिंग करते समय सूची की समझ तेज़ और आसान है। यह अजगर के बजाय एक पर्ल तरीके से अधिक होगा।
पीटर निमरोट

3
-1 सीधे आह्वान के लिए __ne__। दो मूल्यों की तुलना सिर्फ कॉल करने __eq__या __ne__उनमें से किसी एक पर अधिक जटिल प्रक्रिया है । यह यहां सही ढंग से काम कर सकता है क्योंकि आप केवल संख्याओं की तुलना कर रहे हैं, लेकिन सामान्य स्थिति में यह गलत और बग है।
अरन-फे

211

आप एक सूची समझ का उपयोग कर सकते हैं:

def remove_values_from_list(the_list, val):
   return [value for value in the_list if value != val]

x = [1, 2, 3, 4, 2, 2, 3]
x = remove_values_from_list(x, 2)
print x
# [1, 3, 4, 3]

7
आप आइटम को बिना जांचे कैसे निकालेंगे?
अलेक्जेंडर लजबर्गबर्ग

18
यह मूल सूची को संशोधित नहीं करता है लेकिन एक नई सूची देता है।
जॉन वाई

6
@ सेलिनैप: नहीं, यह इष्टतम है क्योंकि यह केवल एक बार सूची को स्कैन करता है। आपके मूल कोड में inऑपरेटर और removeविधि दोनों पूरी सूची को स्कैन करते हैं (जब तक कि उन्हें कोई मैच नहीं मिल जाता है) तो आप सूची को उस तरह से कई बार स्कैन करते हैं।
जॉन कुगेलमैन

4
@mhawke, @ जॉन Y: बस x [:] का उपयोग करें ... = के बजाय x = और यह केवल "x 'नाम को रिबाउंड करने के बजाय" इन-प्लेस "होगा (गति अनिवार्य रूप से एक ही है और X की तुलना में MUCH अधिक तेज़ है। .remove हो सकता है !!!)।
एलेक्स मार्टेली जूल 21'09

10
मैं इसे वोट करता हूं क्योंकि 6 साल के अजगर के बाद भी मुझे लैंबडास समझ में नहीं आता है :)
बेंजामिन

107

यदि मूल सूची को संशोधित किया जाना चाहिए, तो आप स्लाइस असाइनमेंट का उपयोग कर सकते हैं, जबकि अभी भी एक कुशल सूची समझ (या जनरेटर अभिव्यक्ति) का उपयोग कर रहे हैं।

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]

1
@ सेलिनैप: फ़िल्टर सूची को संशोधित नहीं करता है, यह एक नई सूची लौटाता है।
EM

फ़िल्टर और सूची समझ किसी सूची को संशोधित नहीं करते हैं। टुकड़ा काम करता है। और मूल उदाहरण करता है।
ए। कॉफ़ी जूल 22'09

7
मुझे यह पसंद है क्योंकि यह उस सूची को संशोधित करता है जो x को संदर्भित करता है। यदि उस सूची में कोई अन्य संदर्भ हैं, तो वे भी प्रभावित होंगे। यह x = [ v for v in x if x != 2 ]प्रस्तावों के विपरीत है , जो एक नई सूची बनाते हैं और इसे संदर्भित करने के लिए x बदलते हैं, मूल सूची को अछूता छोड़कर।
हेंस

40

पहले पोस्ट के समाधान को और अधिक सार तरीके से दोहराते हुए:

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]

19
यह ओ (एन * एन) है, हालांकि।
हेंस

@Heses O (n) नहीं होगा क्योंकि यह लूप के माध्यम से सिर्फ एक बार और एक ही समय में आइटम को हटा रहा है?
पेंटा

1
विचार करें x = [1] * 10000 + [2] * 1000। लूप बॉडी 1000 बार निष्पादित होती है और .remove () में हर बार 10000 तत्वों को छोड़ना पड़ता है। मेरे लिए O (n * n) जैसी गंध आती है लेकिन कोई प्रमाण नहीं है। मुझे लगता है कि प्रमाण यह मानना ​​होगा कि सूची में 2s की संख्या इसकी लंबाई के लिए आनुपातिक है। यह आनुपातिकता कारक तब बड़े-ओ संकेतन में गायब हो जाता है। सबसे अच्छा मामला, हालांकि, सूची में केवल 2s की निरंतर संख्या, O (n ^ 2) नहीं है, बस O (2n) जो O (n) है।
हेंस

23

सरल उपाय देखें

>>> [i for i in x if i != 2]

यह xबिना किसी तत्व के एक सूची लौटाएगा2


11

उपरोक्त सभी उत्तर (मार्टिन एंडरसन के अलावा) मूल सूची से आइटम हटाने के बजाय वांछित वस्तुओं के बिना एक नई सूची बनाते हैं।

>>> import random, timeit
>>> a = list(range(5)) * 1000
>>> random.shuffle(a)

>>> b = a
>>> print(b is a)
True

>>> b = [x for x in b if x != 0]
>>> print(b is a)
False
>>> b.count(0)
0
>>> a.count(0)
1000

>>> b = a
>>> b = filter(lambda a: a != 2, x)
>>> print(b is a)
False

यह महत्वपूर्ण हो सकता है यदि आपके पास चारों ओर लटकी हुई सूची के अन्य संदर्भ हैं।

सूची को जगह में संशोधित करने के लिए, इस तरह से एक विधि का उपयोग करें

>>> def removeall_inplace(x, l):
...     for _ in xrange(l.count(x)):
...         l.remove(x)
...
>>> removeall_inplace(0, b)
>>> b is a
True
>>> a.count(0)
0

जहां तक ​​गति का सवाल है, मेरे लैपटॉप पर परिणाम हैं (सभी 5000 प्रविष्टि सूची पर 1000 प्रविष्टियों को हटा दिया गया है)

  • सूची समझ - ~ 400us
  • फ़िल्टर - ~ 900us
  • .remove () लूप - 50ms

तो .remove लूप लगभग 100x धीमा है ........ हम्म, शायद एक अलग दृष्टिकोण की आवश्यकता है। सबसे तेज़ जो मैंने पाया है वह सूची समझ का उपयोग कर रहा है, लेकिन फिर मूल सूची की सामग्री को बदल दें।

>>> def removeall_replace(x, l):
....    t = [y for y in l if y != x]
....    del l[:]
....    l.extend(t)
  • removeeall_replace () - 450us

फिर पुरानी सूची के तहत नई सूची को फिर से सौंपना क्यों नहीं? def remove_all(x, l): return [y for y in l if y != x]तत्पश्चातl = remove_all(3,l)
दानीद

@ डनीड यह पहला कोड बॉक्स में दूसरा तरीका है। यह एक नई सूची बनाता है, और आप पुरानी सूची को संशोधित नहीं कर रहे हैं। सूची का कोई अन्य संदर्भ अनफ़िल्टर्ड रहेगा।
पॉल एस

ओह सही। मैं एक विधि को परिभाषित करने में इतना फंस गया, मैंने आपके द्वारा पहले से किए गए सरल असाइनमेंट को अनदेखा कर दिया।
Dannid

7

तुम यह केर सकते हो

while 2 in x:   
    x.remove(2)

3
यह एक बुरा समाधान है, क्योंकि सूची को 2 की n के लिए 2 * n बार ट्रेस किया जाना है।
cxxl

यह उस सूची से जोड़ने या हटाने की अनुशंसा नहीं की जाती है जिसे आप ट्रैवर्स कर रहे हैं। बुरा अभ्यास IMHO।
अमन माथुर

5

पठनीयता की कीमत पर, मुझे लगता है कि यह संस्करण थोड़ा तेज़ है क्योंकि यह सूची को पुन: परीक्षण करने के लिए मजबूर नहीं करता है, इस प्रकार ठीक उसी काम को हटाने के लिए वैसे भी करना पड़ता है:

x = [1, 2, 3, 4, 2, 2, 3]
def remove_values_from_list(the_list, val):
    for i in range(the_list.count(val)):
        the_list.remove(val)

remove_values_from_list(x, 2)

print(x)

आपके द्वारा अपने कोड में दिखाई जाने वाली सूची के लिए, यह दृष्टिकोण सूची माप विधि (जो एक प्रति लौटाता है) की तुलना में लगभग 36% धीमी है, मेरे माप के अनुसार।
djsmith

अच्छा है कि तुम ध्यान दिया हालाँकि, क्योंकि मुझे लगता है कि यह आपके निर्णय को गिरा सकता है, मैं अपने संस्करण की तुलना प्रश्न लेखक द्वारा किए गए पहले प्रस्ताव से कर रहा था।
मार्टिन एंडरसन

4

1.000.000 तत्वों के साथ एक सूची / सरणी के खिलाफ नोमी दृष्टिकोण और समय:

समय:

In [10]: a.shape
Out[10]: (1000000,)

In [13]: len(lst)
Out[13]: 1000000

In [18]: %timeit a[a != 2]
100 loops, best of 3: 2.94 ms per loop

In [19]: %timeit [x for x in lst if x != 2]
10 loops, best of 3: 79.7 ms per loop

निष्कर्ष: लिस्ट कॉम्प्रिहेंशन एप्रोच की तुलना में सुन्नत (मेरी नोटबुक पर) 27 गुना तेज है

पुनश्च यदि आप अपनी नियमित पायथन सूची lstको सुपीरियर सरणी में बदलना चाहते हैं :

arr = np.array(lst)

सेट अप:

import numpy as np
a = np.random.randint(0, 1000, 10**6)

In [10]: a.shape
Out[10]: (1000000,)

In [12]: lst = a.tolist()

In [13]: len(lst)
Out[13]: 1000000

चेक:

In [14]: a[a != 2].shape
Out[14]: (998949,)

In [15]: len([x for x in lst if x != 2])
Out[15]: 998949

4
a = [1, 2, 2, 3, 1]
to_remove = 1
a = [i for i in a if i != to_remove]
print(a)

शायद सबसे अजगर नहीं, लेकिन फिर भी मेरे लिए सबसे आसान है


3

सभी डुप्लिकेट घटनाओं को हटाने और सूची में एक को छोड़ने के लिए:

test = [1, 1, 2, 3]

newlist = list(set(test))

print newlist

[1, 2, 3]

यहाँ परियोजना यूलर के लिए उपयोग किया गया कार्य है:

def removeOccurrences(e):
  return list(set(e))

2
मुझे 250k मान वाले वेक्टर पर ऐसा करने की आवश्यकता थी, और यह एक आकर्षण की तरह काम करता है।
rschwieb

1
इसका जवाब है हाँ! और मैं पूरी तरह से समझता हूं कि अगर एक वेक्टर है जो एक सक्षम प्रोग्रामर के लिए पूरी तरह से पागल लगता है। मैं एक गणितज्ञ के रूप में वहाँ की समस्याओं को हल करता हूँ, समाधानों के अनुकूलन की चिंता नहीं करता, और इससे समाधानों की तुलना में अधिक समय हो सकता है। (हालांकि मुझे 5 मिनट से अधिक समय तक समाधान के लिए कोई धैर्य नहीं है।)
rschwieb

6
यह सूची से किसी भी आदेश को हटा देगा।
22 अप्रैल को asmeurer

4
@JaredBurrows शायद क्योंकि यह सवाल का जवाब नहीं देता है क्योंकि यह वर्तमान में खड़ा है, लेकिन एक बहुत अलग सवाल है।
ड्रेविको

6
-1, यह ओपी के सवाल का जवाब नहीं है। यह डुप्लिकेट को हटाने का एक समाधान है, जो पूरी तरह से अलग मामला है।
एनॉयज जूल

2

मेरा मानना ​​है कि अगर आप सूचियों के आदेश की परवाह नहीं करते हैं, तो यह किसी भी अन्य तरीके से संभवत: तेज है, यदि आप अंतिम क्रम के बारे में ध्यान रखते हैं तो अनुक्रमणिका को मूल से स्टोर करें और उसके द्वारा सहारा लें।

category_ids.sort()
ones_last_index = category_ids.count('1')
del category_ids[0:ones_last_index]

2
मैं समझता हूं कि आपका कहां जा रहा है, लेकिन यह कोड तब तक काम नहीं करेगा, जब आपको स्टार्ट इंडेक्स की जरूरत न हो और सिर्फ 0.
Shedokan

2
for i in range(a.count(' ')):
    a.remove(' ')

ज्यादा आसान मैं मानता हूं।


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

2

चलो

>>> x = [1, 2, 3, 4, 2, 2, 3]

पहले से पहले के रूप में सरल और कुशल समाधान है

>>> x[:] = [v for v in x if v != 2]
>>> x
[1, 3, 4, 3]

एक और संभावना जो कम स्मृति का उपयोग करना चाहिए लेकिन धीमी हो

>>> for i in range(len(x) - 1, -1, -1):
        if x[i] == 2:
            x.pop(i)  # takes time ~ len(x) - i
>>> x
[1, 3, 4, 3]

10% मिलान प्रविष्टियों के साथ लंबाई 1000 और 100000 की सूची के लिए परिणाम: 0.16 बनाम 0.25 एमएस, और 23 बनाम 123 एमएस।

लंबाई 1000 के साथ

लंबाई 100000 के साथ


1

एक पायथन सूची से एक मूल्य के सभी घटनाओं को हटा दें

lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list():
    for list in lists:
      if(list!=7):
         print(list)
remove_values_from_list()

परिणाम: 6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11

वैकल्पिक रूप से,

lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list(remove):
    for list in lists:
      if(list!=remove):
        print(list)
remove_values_from_list(7)

परिणाम: 6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11


"पायथन 'प्रत्येक के लिए नेस्टेड है यदि लूप' 100% सटीकता के साथ काम कर रहा है!"
रफीकुल Apr६

आप सूची को संशोधित नहीं करते हैं आप सिर्फ तत्वों को प्रिंट करते हैं। सूची के रूप में एक सूची का नामकरण भी भ्रामक है
kon psych

0

यदि आपने बिल्ट-इन filterनहीं किया है या अतिरिक्त स्थान का उपयोग नहीं करना चाहते हैं और आपको एक रैखिक समाधान की आवश्यकता है ...

def remove_all(A, v):
    k = 0
    n = len(A)
    for i in range(n):
        if A[i] !=  v:
            A[k] = A[i]
            k += 1

    A = A[:k]

0
hello =  ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
#chech every item for a match
for item in range(len(hello)-1):
     if hello[item] == ' ': 
#if there is a match, rebuild the list with the list before the item + the list after the item
         hello = hello[:item] + hello [item + 1:]
print hello

['नमस्ते दुनिया']


कृपया स्पष्टीकरण के साथ अपने उत्तर को विस्तृत करने का प्रयास करें।
3

0

मैंने सिर्फ एक सूची के लिए ऐसा किया। मैं सिर्फ एक शुरुआत हूं। थोड़ा और अधिक उन्नत प्रोग्रामर निश्चित रूप से इस तरह से एक फ़ंक्शन लिख सकता है।

for i in range(len(spam)):
    spam.remove('cat')
    if 'cat' not in spam:
         print('All instances of ' + 'cat ' + 'have been removed')
         break

0

हम delया तो सभी जगह का उपयोग कर सकते हैं या pop:

import random

def remove_values_from_list(lst, target):
    if type(lst) != list:
        return lst

    i = 0
    while i < len(lst):
        if lst[i] == target:
            lst.pop(i)  # length decreased by 1 already
        else:
            i += 1

    return lst

remove_values_from_list(None, 2)
remove_values_from_list([], 2)
remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)], 2)
print(len(lst))

अब दक्षता के लिए:

In [21]: %timeit -n1 -r1 x = random.randrange(0,10)
1 loop, best of 1: 43.5 us per loop

In [22]: %timeit -n1 -r1 lst = [random.randrange(0, 10) for x in range(1000000)]
g1 loop, best of 1: 660 ms per loop

In [23]: %timeit -n1 -r1 lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)]
    ...: , random.randrange(0,10))
1 loop, best of 1: 11.5 s per loop

In [27]: %timeit -n1 -r1 x = random.randrange(0,10); lst = [a for a in [random.randrange(0, 10) for x in
    ...:  range(1000000)] if x != a]
1 loop, best of 1: 710 ms per loop

जैसा कि हम देखते हैं कि इन-प्लेस संस्करण remove_values_from_list()को किसी अतिरिक्त मेमोरी की आवश्यकता नहीं है, लेकिन इसे चलाने में इतना अधिक समय लगता है:

  • 11 सेकंड के लिए inplace हटाए गए मान
  • सूची की समझ के लिए 710 मिली सेकंड , जो स्मृति में एक नई सूची आवंटित करता है

0

किसी ने समय और स्थान की जटिलता के लिए एक इष्टतम उत्तर पोस्ट नहीं किया है, इसलिए मैंने सोचा कि मैं इसे एक शॉट दूंगा। यहां एक समाधान है जो एक नई सरणी बनाने और एक कुशल समय जटिलता के बिना एक विशिष्ट मूल्य की सभी घटनाओं को हटा देता है। दोष यह है कि तत्व आदेश को बनाए नहीं रखते हैं

समय जटिलता: O (n)
अतिरिक्त स्थान जटिलता: O (1)

def main():
    test_case([1, 2, 3, 4, 2, 2, 3], 2)     # [1, 3, 3, 4]
    test_case([3, 3, 3], 3)                 # []
    test_case([1, 1, 1], 3)                 # [1, 1, 1]


def test_case(test_val, remove_val):
    remove_element_in_place(test_val, remove_val)
    print(test_val)


def remove_element_in_place(my_list, remove_value):
    length_my_list = len(my_list)
    swap_idx = length_my_list - 1

    for idx in range(length_my_list - 1, -1, -1):
        if my_list[idx] == remove_value:
            my_list[idx], my_list[swap_idx] = my_list[swap_idx], my_list[idx]
            swap_idx -= 1

    for pop_idx in range(length_my_list - swap_idx - 1):
        my_list.pop() # O(1) operation


if __name__ == '__main__':
    main()

-1

गति के बारे में!

import time
s_time = time.time()

print 'start'
a = range(100000000)
del a[:]
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 3.25

s_time = time.time()
print 'start'
a = range(100000000)
a = []
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 2.11

-3
p=[2,3,4,4,4]
p.clear()
print(p)
[]

केवल पायथन 3 के साथ


2
प्रफुल्लित करने वाला, यह पूछे गए प्रश्न के दायरे में है और सही है।
एरिक

मैं यह नहीं देखता कि यह कैसे सही है। यह सूची से सभी आइटमों को हटा देगा , सभी मानों की नहीं
जॉर्जी

-3

क्या गलत है:

Motor=['1','2','2']
For i in Motor:
       If i  != '2':
       Print(i)
Print(motor)

एनाकोंडा का उपयोग करना


2
कृपया अपनी कोड की पंक्तियों की व्याख्या करें ताकि अन्य उपयोगकर्ता इसकी कार्यक्षमता को समझ सकें। धन्यवाद!
इग्नासियो आरा

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