2010-08-22 12 views
26

क्या ऐसा करने के लिए एक अंतर्निहित विधि है? यदि नहीं, तो मैं बहुत अधिक लागत के बिना यह कैसे कर सकता हूं?मैं अजगर में एक फ़ाइल से यादृच्छिक रेखा कैसे पढ़ूं?

+0

@ ग्रेग यह पर्ल है, पायथन – quantumSoup

+2

@quantumSoup नहीं: प्रश्न अपने उदाहरणों में पर्ल का उपयोग करता है, लेकिन सवाल भाषा अज्ञेयवादी है। सबसे उपयोगी उत्तर छद्म कोड का उपयोग करते हैं, आसानी से आपकी पसंद की भाषा में अनुवाद किया जाता है। –

+0

धन्यवाद, मुझे यह भी बहुत मदद मिली: http://mail.python.org/pipermail/tutor/2007-July/055635.html हालांकि आपको उन्हें स्मृति में पढ़ना होगा। – Shane

उत्तर

51

नहीं में निर्मित है, लेकिन एल्गोरिथ्म R(3.4.2) नुथ के से (वाटरमैन के "जलाशय एल्गोरिथ्म") "आर्ट ऑफ़ कंप्यूटर प्रोग्रामिंग" अच्छा है (एक बहुत सरलीकृत संस्करण में):

import random 

def random_line(afile): 
    line = next(afile) 
    for num, aline in enumerate(afile): 
     if random.randrange(num + 2): continue 
     line = aline 
    return line 

num + 2 अनुक्रम का उत्पादन 2, 3, 4 ... randrange1.0/(num + 2) की संभाव्यता के साथ 0 होगा - और यह संभावना है जिसके साथ हमें वर्तमान में चयनित लाइन को प्रतिस्थापित करना होगा (संदर्भित एल्गोरिदम के नमूना आकार 1 का विशेष मामला - देखें सहीता के प्रमाण के लिए Knuth की पुस्तक == और निश्चित रूप से हम स्मृति में फिट होने के लिए एक छोटे से पर्याप्त "जलाशय" के मामले में भी हैं; -) ... और वास्तव में संभावना जो हम करते हैं।

+1

+1 से मिक्स से पायथन – aaronasterling

+2

अनुवाद के लिए यह जलाशय नमूना है, है ना? – HenryR

+6

मैंने हमेशा सोचा है कि 'random.choice()' फ़ंक्शन को मनमाने ढंग से इटरेटर्स के साथ-साथ अनुक्रमों पर भी काम करना चाहिए, जो उपर्युक्त एल्गोरिदम को लागू करते हैं। –

1

एक यादृच्छिक स्थिति की तलाश करें, एक रेखा पढ़ें और इसे छोड़ दें, फिर एक और पंक्ति पढ़ें। लाइनों का वितरण सामान्य नहीं होगा, लेकिन यह हमेशा कोई फर्क नहीं पड़ता।

+3

विशेष रूप से, यह पहली पंक्ति का चयन करना असंभव बनाता है (साथ ही प्रत्येक पिछली पंक्ति की लंबाई के अनुपात के साथ अन्य लाइनों को चुनना असंभव बनाता है)। मेरा ए सामान्य वितरण का उत्पादन नहीं करता है (यह अजीब होगा - क्या मतलब है, क्या भिन्नता ?!), लेकिन एक समान, जो कि "यादृच्छिक" के लिए ओपी के अर्थ को पूरा करने की कुछ और संभावना है। –

+0

@AlexMartelli द्वारा इंगित की गई समस्या को दूर करने के लिए, यादृच्छिक खोज आपको अंतिम पंक्ति तक ले जाने पर पहली पंक्ति चुनें। लेकिन यहां एक और मुद्दा यह है कि अन्य लाइनों के अपेक्षाकृत अधिक शब्द वाले रेखा में चयन करने की उच्च संभावना होगी। –

9

यह निर्भर करता है कि "बहुत अधिक" ओवरहेड से आपका क्या मतलब है। यदि स्मृति में पूरी फ़ाइल को संग्रहीत करना संभव है, तो

import random 

random_lines = random.choice(open("file").readlines()) 

कुछ ऐसा चाल करेगा।

23
import random 
lines = open('file.txt').read().splitlines() 
myline =random.choice(lines) 
print(myline) 

बहुत लंबे फ़ाइल के लिए: यह लंबाई के आधार पर फाइल में यादृच्छिक जगह की तलाश और स्थिति (या न्यू लाइन और फ़ाइल के अंत में) के बाद दो नई पंक्ति वर्ण पाते हैं। यदि मूल खोज स्थिति < 100 थी तो अंतिम फ़ाइल के अंदर समाप्त होने पर फ़ाइल की शुरुआत से पहले या उससे पहले 100 अक्षर फिर से करें।

हालांकि इस जटिल खत्म हो गया है के रूप में फ़ाइल यह सूची बनाने के लिए और random.choice ले iterator.So है (यदि आप कई, उपयोग random.sample की जरूरत है):

import random 
print(random.choice(list(open('file.txt')))) 
+9

यदि कार्य केवल एक पंक्ति को पढ़ना है, तो पूर्ण फ़ाइल को स्मृति में लोड करने के लिए यह समझ में नहीं आता है। – iankit

6

हालांकि मैं चार साल देर से कर रहा हूँ, मुझे लगता है कि मेरे पास सबसे तेज़ समाधान है। हाल ही में मैंने linereader नामक एक पायथन पैकेज लिखा है, जो आपको फ़ाइल हैंडल के पॉइंटर्स में हेरफेर करने की अनुमति देता है। के रूप में linereader एक विशेष प्रारूप में आउटपुट फ़ाइल संकलित करने के लिए है

from random import randint 
from linereader import dopen 

length = #lines in file 
filename = #directory of file 

file = dopen(filename) 
random_line = file.getline(randint(1, length)) 

पहली बार यह हो जाए, सबसे खराब है:

यहाँ इस पैकेज के साथ एक यादृच्छिक लाइन हो रही करने के लिए सरल समाधान है। ऐसा करने के बाद, लाइनreader फ़ाइल से किसी भी लाइन को जल्दी से एक्सेस कर सकता है, फ़ाइल का आकार चाहे जो भी हो।

यदि आपकी फ़ाइल बहुत छोटी है (एमबी में फिट करने के लिए पर्याप्त छोटा है), तो आप dopen को copen के साथ प्रतिस्थापित कर सकते हैं, और यह स्मृति के भीतर फ़ाइल का कैश प्रविष्टि बनाता है। न केवल यह तेज़ है, लेकिन आपको फ़ाइल में लाइनों की संख्या मिलती है क्योंकि यह स्मृति में लोड होती है; यह आपके लिए किया जाता है। यादृच्छिक रेखा संख्या उत्पन्न करने के लिए आपको बस इतना करना है। इसके लिए यहां कुछ उदाहरण कोड दिया गया है।

from random import randint 
from linereader import copen 

file = copen(filename) 
lines = file.count('\n') 
random_line = file.getline(randint(1, lines)) 

मुझे अभी वाकई खुशी हुई क्योंकि मैंने किसी ऐसे व्यक्ति को देखा जो मेरे पैकेज से लाभ उठा सकता है! मृत उत्तर के लिए खेद है, लेकिन पैकेज निश्चित रूप से कई अन्य समस्याओं पर लागू किया जा सकता है।

+0

मेरे पास ValueError लाइन संख्या थी। नहीं मिला, लेकिन रेखा संख्या। फ़ाइल के आकार से कम था। – kakarukeys

2

यदि आप पूरी फ़ाइल को पढ़ना नहीं चाहते हैं, तो आप फ़ाइल के बीच में खोज सकते हैं, फिर नई लाइन के लिए पीछे की ओर खोज सकते हैं और readline पर कॉल कर सकते हैं।

यहाँ एक python3 स्क्रिप्ट जो सिर्फ इस करता है, इस विधि के साथ

एक नुकसान यह छोटी पंक्तियां दिखाने के निचले संभावना है।

def read_random_line(f, chunk_size=16): 
    import os 
    import random 
    with open(f, 'rb') as f_handle: 
     f_handle.seek(0, os.SEEK_END) 
     size = f_handle.tell() 
     i = random.randint(0, size) 
     while True: 
      i -= chunk_size 
      if i < 0: 
       chunk_size += i 
       i = 0 
      f_handle.seek(i, os.SEEK_SET) 
      chunk = f_handle.read(chunk_size) 
      i_newline = chunk.rfind(b'\n') 
      if i_newline != -1: 
       i += i_newline + 1 
       break 
      if i == 0: 
       break 
     f_handle.seek(i, os.SEEK_SET) 
     return f_handle.readline() 
0

आप एक सेट() जो उनके आदेश बेतरतीब ढंग से बदल जाएगा में लाइनों जोड़ सकते हैं।

for line in f: 
    print(line) 
0

यह:

print(list(f)[2]) 

सेट में सभी लाइनों को सूचीबद्ध करने के:

print(next(iter(f))) 

3 लाइन ढूंढने के लिए:

filename=open("lines.txt",'r') 
f=set(filename.readlines()) 
filename.close() 

1 लाइन लगाने के लिए भारी हो सकता है, लेकिन यह मुझे लगता है कि काम करता है? (कम से कम पाठ फ़ाइलों के लिए)

import random 
choicefile=open("yourfile.txt","r") 
linelist=[] 
for line in choicefile: 
    linelist.append(line) 
choice=random.choice(linelist) 
print(choice) 

यह एक फ़ाइल की प्रत्येक पंक्ति पढ़ता है, और एक सूची में जोड़ देता है। फिर यह सूची से एक यादृच्छिक रेखा चुनता है। आप एक बार इसे चुना है लाइन को निकालना चाहते हैं, बस

linelist.remove(choice) 

आशा इस मदद मिल सकती है, लेकिन कम से कम बिना किसी अतिरिक्त मॉड्यूल और आयात (अलग यादृच्छिक से) और अपेक्षाकृत हल्के।

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