यहां एक साधारण समाधान है जो प्रति नमूना फ़ाइलों के माध्यम से केवल एक को पास करता है। यदि आप जानते हैं कि आप फ़ाइलों से कितने सामान नमूना लेंगे, तो यह शायद इष्टतम है।
पहला ऑफ नमूना फ़ंक्शन है। यह उसी एल्गोरिदम का उपयोग करता है जो @NedBatchelder को पहले के उत्तर पर एक टिप्पणी में लिंक किया गया था (हालांकि पर्ल कोड दिखाया गया है कि कई लोगों के बजाय केवल एक पंक्ति का चयन किया गया है)। यह लाइनों के पुनरावर्तनीय से मूल्यों का चयन करता है, और केवल वर्तमान में चयनित लाइनों को किसी भी समय (साथ ही अगली उम्मीदवार लाइन) में स्मृति में रखा जाना चाहिए। यह ValueError
उठाता है यदि अनुरोधनीय नमूना आकार की तुलना में पुनरावृत्त कम मूल्य है।
import random
def random_sample(n, items):
results = []
for i, v in enumerate(items):
r = random.randint(0, i)
if r < n:
if i < n:
results.insert(r, v) # add first n items in random order
else:
results[r] = v # at a decreasing rate, replace random items
if len(results) < n:
raise ValueError("Sample larger than population.")
return results
संपादित करें: एक और सवाल में, उपयोगकर्ता @DzinX देखा है कि इस कोड में insert
के उपयोग आप मूल्यों की एक बहुत बड़ी संख्या में नमूने रहे हैं प्रदर्शन बुरा (O(N^2)
) बनाता है। उनका बेहतर संस्करण जो उस मुद्दे से बचाता है here है। /संपादित करें
अब हमें अपने फ़ंक्शन के नमूने के लिए आइटमों के उपयुक्त पुन: प्रयोज्य बनाने की आवश्यकता है। यहां जनरेटर का उपयोग करके मैं इसे कैसे करूँगा। यह कोड केवल एक फ़ाइल को एक ही समय में खुला रखेगा, और इसे एक समय में स्मृति में एक से अधिक पंक्ति की आवश्यकता नहीं है। वैकल्पिक exclude
पैरामीटर, यदि मौजूद है, तो set
होना चाहिए जिसमें पिछले रन पर चयनित लाइनें हों (और इसलिए इसे फिर से नहीं दिया जाना चाहिए)।
import os
def lines_generator(base_folder, exclude = None):
for dirpath, dirs, files in os.walk(base_folder):
for filename in files:
if filename.endswith(".txt"):
fullPath = os.path.join(dirpath, filename)
with open(fullPath) as f:
for line in f:
cleanLine = line.strip()
if exclude is None or cleanLine not in exclude:
yield cleanLine
अब, हम सिर्फ एक आवरण समारोह उन दो टुकड़ों को एक साथ बांधने के लिए (और देखा लाइनों के सेट को प्रबंधित) की जरूरत है। यह आकार n
या count
नमूने की एक सूची का एक नमूना वापस कर सकता है, इस तथ्य का लाभ उठाते हुए कि एक यादृच्छिक नमूना से एक टुकड़ा भी एक यादृच्छिक नमूना है।
_seen = set()
def get_sample(n, count = None):
base_folder = r"C:\Tasks"
if count is None:
sample = random_sample(n, lines_generator(base_folder, _seen))
_seen.update(sample)
return sample
else:
sample = random_sample(count * n, lines_generator(base_folder, _seen))
_seen.update(sample)
return [sample[i * n:(i + 1) * n] for i in range(count)]
यह ऐसे इस्तेमाल किया जा सकता:
def main():
s1 = get_sample(10)
print("Sample1:", *s1, sep="\n")
s2, s3 = get_sample(10,2) # get two samples with only one read of the files
print("\nSample2:", *s2, sep="\n")
print("\nSample3:", *s3, sep="\n")
s4 = get_sample(5000) # this will probably raise a ValueError!
आप हर फ़ाइल से 10 यादृच्छिक लाइनों या total_ _in 10 लाइनों करना चाहते हैं? –
धन्यवाद, कुल में 10 यादृच्छिक रेखाएं। – user1582596
क्या इन फ़ाइलों में लाइनें अद्वितीय हैं? क्या आप रनों के बीच लाइनों/फ़ाइलों को जोड़ने की उम्मीद करते हैं? क्या इन फ़ाइलों में दसियों या लाखों रेखाएं हैं? –