2009-12-08 14 views
5

के आधार पर किसी सूची से किसी तत्व को निकालना, मैं सूची से तत्व को हटाना चाहता हूं, जैसे कि तत्व 'X' या 'N' है। मुझे एक बड़े जीनोम के लिए आवेदन करना है। यहाँ एक उदाहरण है:एक अनुमानित

इनपुट:

codon=['AAT','XAC','ANT','TTA'] 

उम्मीद उत्पादन:

codon=['AAT','TTA'] 
+2

जब आप "सूची" से "निकालें" के लिए अजगर संदर्भ पृष्ठों में देखा, क्या तुम मिला: एक सुधार के लायक कर रही है, और रेगुलर एक्सप्रेशन के उपयोग शायद जाने के लिए रास्ता नहीं है होना करने के लिए? कुछ भी? कृपया पाइथन दस्तावेज़ों की जांच करें, और उसके बाद अपने प्रश्न को कुछ विशिष्ट के साथ अपडेट करें। –

+0

संकेत: अपनी खोज यहां शुरू करें: http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-list-tuple-buffer-xrange –

+0

अच्छी तरह से कहा गया प्रश्न। –

उत्तर

2

वहाँ भी फिल्टर

list = filter(lambda x: 'X' not in x and 'N' not in x, list) 
6

का उपयोग कर आधार उद्देश्य

के लिए यह करने की विधि है
>>> [x for x in ['AAT','XAC','ANT','TTA'] if "X" not in x and "N" not in x] 
['AAT', 'TTA'] 

लेकिन अगर आप डेटा की बड़ी राशि है, मैं सुझाव है कि आप dict का उपयोग करें या

स्थापित करने के लिए और आप कई एक्स और एन से अन्य पात्रों की, तो आप इस

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(ch for ch in list(x) if ch in ["X","N","Y","Z","K","J"])] 
['AAT', 'TTA'] 

नोट की तरह कर सकते हैं: list(x) सिर्फ x हो सकता है, और ["X","N","Y","Z","K","J"] केवल "XNYZKJ" हो सकता है, और gnibbler उत्तर देखें, उसने सबसे अच्छा किया।

+0

पढ़ा नहीं है आपने मुझे बस इसे हराया है। मेरा एक ही जवाब था। –

+0

इसे ले लो, सबसे तेज़ एक –

+0

स्थिति लिखने का एक बेहतर तरीका होना चाहिए। लेन की तरह कुछ (सेट ("एक्स एन"।विभाजन()) | सेट (एक्स)) == 0 अच्छा और आसान यदि आपके पास हटाने के लिए और चीजें हैं लेकिन यह धीमी होने की संभावना है। –

2
  1. filter(lambda x: 'N' not in x or 'X' not in x, your_list)
  2. your_list = [x for x in your_list if 'N' not in x or 'X' not in x]
+0

पर सेट का उपयोग कर एक संस्करण जोड़ा है यहां की स्थिति गलत है। यह x में नहीं होना चाहिए और 'एक्स' x में नहीं है, या नहीं (एक्स में 'एन' या एक्स में 'एक्स') होना चाहिए। –

4

एक और नहीं सबसे तेज़ तरीका है, लेकिन मैं यह अच्छी तरह

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(y in x for y in "XN")] 
['AAT', 'TTA'] 

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not set("XN")&set(x)] 
['AAT', 'TTA'] 

पढ़ता है इस तरह से लंबे समय तक कोडोन के लिए तेजी से हो जाएगा (यह मानते हुए कुछ पुनरावृत्ति होती है) लगता है

codon = ['AAT','XAC','ANT','TTA'] 
def pred(s,memo={}): 
    if s not in memo: 
     memo[s]=not any(y in s for y in "XN") 
    return memo[s] 

print filter(pred,codon) 

यहाँ विधि जेम्स ब्रूक्स ने सुझाव दिया है, आप अपने डेटा

codon = ['AAT','XAC','ANT','TTA'] 
def pred(s,memo={}): 
    if s not in memo: 
     memo[s]= not set("XN")&set(s) 
    return memo[s] 

print filter(pred,codon) 

इस नमूने कोडोन के लिए के लिए है जो देखने के लिए तेजी से परीक्षण करने के लिए होगा, सेट का उपयोग कर संस्करण के बारे में 10% धीमी है

+0

आपके पास हमेशा सबसे छोटा होता है, :-) +1 – YOU

+0

यह सबसे अच्छा जवाब होना चाहिए! – YOU

+0

अच्छा! 'Pred' के लिए कोड अंतर्निहित dict.setdefault विधि का उपयोग कर सकता है (जैसा कि मेरे उत्तर में प्रमाणित है); मुझे लगता है कि setdefault संस्करण तेज है। – EOL

0

एस। मार्क ने यहां अनुरोध किया है कि मेरा संस्करण है। यह शायद धीमा है लेकिन जो भी हटाया जाता है उसे बदलने में आसान बनाता है।

def filter_genome(genome, killlist = set("X N".split()): 
    return [codon for codon in genome if 0 == len(set(codon) | killlist)] 
+0

इस उत्तर में सेट ऑपरेटर '&' होना चाहिए, न कि '।'। –

2

संपूर्ण सूची को डुप्लिकेट करने का कोई कारण? कैसे के बारे में:

>>> def pred(item, haystack="XN"): 
...  return any(needle in item for needle in haystack) 
... 
>>> lst = ['AAT', 'XAC', 'ANT', 'TTA'] 
>>> idx = 0 
>>> while idx < len(lst): 
...  if pred(lst[idx]): 
...   del lst[idx] 
...  else: 
...   idx = idx + 1 
... 
>>> lst 
['AAT', 'TTA'] 

मुझे पता है कि सूची comprehensions हैं सब क्रोध इन दिनों, लेकिन हम सही बिना किसी कारण के यह नकल नहीं करना चाहती है, तो सूची लंबी है? आप अगले चरण के लिए इस लेने के लिए और एक अच्छा उपयोगिता समारोह बना सकते हैं:

>>> def remove_if(coll, predicate): 
...  idx = len(coll) - 1 
...  while idx >= 0: 
...   if predicate(coll[idx]): 
...    del coll[idx] 
...   idx = idx - 1 
...  return coll 
... 
>>> lst = ['AAT', 'XAC', 'ANT', 'TTA'] 
>>> remove_if(lst, pred) 
['AAT', 'TTA'] 
>>> lst 
['AAT', 'TTA'] 
+0

इस तरह सी सी डेवलपर समस्या के बारे में सोचता है। पाइथन का उपयोग करके, विशेष सूचियों में, आप पहले से ही बहुत सारी दक्षता बलिदान कर रहे हैं तो आप सूची में सूची को संशोधित करने की परवाह क्यों करेंगे? –

+0

असल में, एक सी ++ डेवलपर ... मुझे लगता है कि इसे जगह में संशोधित करना ओपी ने पूछा था। मैं आमतौर पर दक्षता की परवाह करता हूं भले ही डेटा सेट बड़ा हो, भले ही बड़ी मेमोरी डुप्लिकेशंस आमतौर पर मिनटों के बजाय घंटे या मेमोरी से बाहर चलने का मतलब हो, यदि आप बड़े डेटा सेट से निपट रहे हैं। इस बात का जिक्र नहीं है कि सूची की समझ और 'नहीं' और 'और' के साथ-साथ आप जो भी कर रहे हैं उसे छुपाएं। List_ से कुछ आइटमों को हटाने के बजाय आप आइटम्स_ के बिना सूची को डुप्लिकेट कर रहे हैं। मुझे लगता है कि मैं सादगी और स्पष्टता पसंद करते हैं। –

+1

दूसरे उदाहरण में 'idx = idx - 1' होना चाहिए। सूची समझ या फ़िल्टर() का उपयोग करने का कारण यह है कि लूप सी में है, इसलिए आमतौर पर बहुत तेज़ होता है। –

1

मैं के gnibbler Memoization तरह एक बहुत दृष्टिकोण। बड़े डेटा सेट पर बड़ी तस्वीर में ज्ञापन का उपयोग करने वाली विधि को समान रूप से तेज़ होना चाहिए, क्योंकि ज्ञापन शब्दकोश को जल्दी से भरना चाहिए और वास्तविक परीक्षण शायद ही कभी किया जाना चाहिए।इस बात को ध्यान में रखते हुए, हम बड़े डेटा सेट के लिए प्रदर्शन को और भी बेहतर बनाने में सक्षम होना चाहिए। (यह बहुत कम कीमतों के लिए कुछ कीमतों पर आता है, लेकिन उन लोगों की परवाह कौन करता है?) निम्नलिखित कोड को केवल दो बार की बजाय ज्ञापन के दौरान एक आइटम को देखना होगा (एक बार सदस्यता निर्धारित करने के लिए, निकालने के लिए दूसरा महत्व)।

codon = ['AAT', 'XAC', 'ANT', 'TTA'] 
def pred(s,memo={}): 
    try: 
     return memo[s] 
    except KeyError: 
     memo[s] = not any(y in s for y in "XN") 
    return memo[s] 

filtered = filter(pred, codon) 

जैसा कि मैंने कहा था, जीनोम बड़ा होने पर यह काफी तेज़ होना चाहिए (या कम से कम बहुत छोटा नहीं)।

आप सूची नकल करने, लेकिन सिर्फ फ़िल्टर की गई सूची से अधिक पुनरावृति, की तरह कुछ करना नहीं चाहते हैं:

for item in (item for item in codon if pred): 
    do_something(item) 
+0

प्रयास करें ... आपके द्वारा उपयोग की जाने वाली संरचना को छोड़कर अंतर्निहित dict.setdefault के बराबर है (उदाहरण के लिए मेरा उत्तर देखें)। – EOL

+0

वास्तव में एक सूक्ष्म अंतर है: setdefault के साथ "डिफ़ॉल्ट" अभिव्यक्ति का मूल्यांकन किया जाता है चाहे कोई फर्क नहीं पड़ता! इस अभिव्यक्ति में धीमी भविष्यवाणी है जिसे हम टालने का प्रयास कर रहे हैं, और ज्ञापन को बेकार बना देता है। कोशिश/छोड़कर संस्करण केवल कुंजीइरर होने पर पूर्वानुमान का मूल्यांकन करता है। – musicinmybrain

+0

@musicinmybrain: अच्छी पकड़! धन्यवाद! जनरेटर अभिव्यक्ति का उपयोग करने के लिए – EOL

0

यह (asympotically) तेजी से एक रेगुलर एक्सप्रेशन में कई बार खोज से उपयोग करने के लिए है एक निश्चित चरित्र के लिए एक ही स्ट्रिंग: असल में, एक नियमित अभिव्यक्ति के साथ अनुक्रम केवल एक बार पढ़ा जाता है (उदाहरण के लिए, जब अक्षरों को नहीं मिलता है, तो अक्षरों को नहीं मिलता है)। gnibbler के Memoization के साथ, नियमित अभिव्यक्ति दृष्टिकोण पढ़ता है:

import re 
remove = re.compile('[XN]').search 

codon = ['AAT','XAC','ANT','TTA'] 
def pred(s,memo={}): 
    if s not in memo: 
     memo[s]= not remove(s) 
    return memo[s] 

print filter(pred,codon) 

यह होना चाहिए (asymptotically) "में" का उपयोग या "सेट" जाँच करता है की तुलना में तेजी (यानी, इसके बाद के संस्करण कोड काफी देर तक तार के लिए तेजी से होना चाहिए s)।

मैं मूल रूप से सोचा था कि gnibbler के जवाब dict.setdefault() के साथ एक तेजी से और अधिक कॉम्पैक्ट तरह से लिखा जा सकता है:

codon = ['AAT','XAC','ANT','TTA'] 
def pred(s,memo={}): 
    return memo.setdefault(s, not any(y in s for y in "XN")) 

print filter(pred,codon) 

लेकिन, जैसा कि gnibbler बताया गया है, SetDefault में मान हमेशा मूल्यांकन किया जाता है (भले ही सिद्धांत रूप में, इसका मूल्यांकन तब किया जा सकता है जब शब्दकोश कुंजी नहीं मिलती)।

+0

याद रखें कि setdefault के लिए दूसरा पैरामीटर हमेशा मूल्यांकन किया जाता है, हालांकि ज्ञापन –

+0

@gnibbler को हराया जाता है: आप सही हैं, धन्यवाद! – EOL

1

यदि आप अत्यधिक बड़ी सूचियों से निपट रहे हैं, तो आप उन विधियों का उपयोग करना चाहते हैं जिनमें पूरी सूची को पूरी तरह से करने की आवश्यकता नहीं है।

आपका सबसे अच्छा शर्त होने की संभावना एक फिल्टर समारोह बनाने के लिए किया जाएगा, और itertools.ifilter का उपयोग कर, उदा .:

new_seq = itertools.ifilter(lambda x: 'X' in x or 'N' in x, seq) 

यह वास्तव में सूची में प्रत्येक तत्व का परीक्षण defers जब तक आप वास्तव में इस पर पुनरावृति है। नोट यदि आपको फ़िल्टर अनुक्रम फ़िल्टर कर सकते हैं कि बस के रूप में आप कर सकते हैं मूल अनुक्रम:

new_seq1 = itertools.ifilter(some_other_predicate, new_seq) 

संपादित करें:

इसके अलावा, एक छोटे से परीक्षण से पता चलता है कि memoizing एक सेट में प्रविष्टि नहीं मिली के लिए पर्याप्त मिलने की संभावना है

seq = ['AAT','XAC','ANT','TTA'] 
>>> p = re.compile('[X|N]') 
>>> timeit.timeit('[x for x in seq if not p.search(x)]', 'from __main__ import p, seq') 
3.4722548536196314 
>>> timeit.timeit('[x for x in seq if "X" not in x and "N" not in x]', 'from __main__ import seq') 
1.0560532134670666 
>>> s = set(('XAC', 'ANT')) 
>>> timeit.timeit('[x for x in seq if x not in s]', 'from __main__ import s, seq') 
0.87923730529996647 
+0

हालांकि new_seq एक जेनरेटर है जो ठीक है अगर आप इसे लूप करना चाहते हैं, लेकिन कभी-कभी आपको इसके बजाय एक सूची की आवश्यकता होगी। –

+0

यदि आप बेहद बड़ी सूचियों के साथ काम कर रहे हैं, तो कहीं भी आप इटेरबल्स के बजाय सूचियों का उपयोग कर रहे हैं, यह एक परेशानी का स्थान होने की संभावना है। आप जनरेटर को एक सूची में छोटा रूप से रूपांतरित कर सकते हैं - 'सूची (new_seq) 'वह करता है - लेकिन यह सूची में प्रत्येक तत्व पर जाकर करता है। यदि आप दो मिलियन कोडन की सूची के साथ काम कर रहे हैं, तो आप वास्तव में केवल एक बार ऐसा करना चाहते हैं। –

संबंधित मुद्दे