मुझे यह समझने में समस्या हो रही है कि यह कैसे करें। मेरे पास जन्मदिन को संभालने वाली एक txt फ़ाइल है:

**January birthdays:**
**17** - !@Mark
**4** - !@Jan
**15** - !@Ralph

**February birthdays:**
**27** - !@Steve
**19** - !@Bill
**29** - !@Bob

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

उदाहरण के लिए जनवरी होना चाहिए:

**January birthdays:**
**4** - !@Jan
**15** - !@Ralph 
**17** - !@Mark

मैंने क्या विचार-मंथन किया है:

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

मैंने अगले महीने की लाइन जैसी स्टॉप कंडीशन तक पढ़ने के लिए partial() का उपयोग करने पर भी विचार किया और फिर उसके आधार पर किसी तरह सॉर्ट किया।

क्या पाइथन ऐसा कुछ करने का कोई आसान तरीका प्रदान करता है?

0
eberryi 26 जिंदा 2021, 23:39

3 जवाब

सबसे बढ़िया उत्तर

आप इसे निम्नानुसार कर सकते हैं।

कोड

import re

def order_month(month_of_entries):
    '''
        Order lines for a Month of entries
    '''
    # Sort key based upon number in line
    # First line in Month does not have a number, 
    # so key function returns 0 for it so it stays first
    month_of_entries.sort(key=lambda x: int(p.group(0)) if (p:=re.search('\d+', x)) else 0)
            
# Process input file
with open('input.txt', 'r') as file:
    results = []
    months_data = []
    for line in file:
        line = line.rstrip()
        if line:
            months_data.append(line)
        else:
            # blank line
            # Order files for this month
            order_month(months_data)
            results.append(months_data)
            
            # Setup for next month
            months_data = []
    else:
        # Reached end of file
        # Order lines for last month
        if months_data:
            order_entries(months_data)
            results.append(months_data)
               
# Write to output file
with open('output.txt', 'w') as file:
    for i, months_data in enumerate(results):
        # Looping over each month
        for line in months_data:
            file.write(line + '\n')
        # Add blank line if not last month
        if i < len(results) - 1:
            file.write('\n')           
         

आउटपुट

**January birthdays:**
**4** - !@Jan
**15** - !@Ralph
**17** - !@Mark

**February birthdays:**
**19** - !@Bill
**27** - !@Steve
**29** - !@Bob

वैकल्पिक, यदि आवश्यक हो तो महीनों को भी क्रमबद्ध करें

import re
from itertools import accumulate
from datetime import date
    
def find_day(s, pattern=re.compile(r'\d+')): 
    return 99 if not s.strip() else int(p.group(0)) if (p:=pattern.search(s)) else 0

def find_month(previous, s, pattern = re.compile(fr"^\*\*({'|'.join(months_of_year)})")):
    ' Index of Month in year (i.e. 1-12)'
    return months_of_year.index(p.group(1)) if (p:=pattern.search(s)) else previous

with open('test.txt') as infile:
    lines = infile.readlines()
    
months_of_year = [date(2021, i, 1).strftime('%B') for i in range(1, 13)] # Months of year
months = list(accumulate(lines, func = find_month, initial = ''))[1:]   # Create Month for each line
days = (find_day(line) for line in lines)                               # Day for each line

# sort lines based upon it's month and day
result = (x[-1] for x in sorted(zip(months, days, lines), key = lambda x: x[:2]))
    
with open('output.txt', 'w') as outfile:
    outfile.writelines(result)
    
1
DarrylG 27 जिंदा 2021, 19:57

यह प्रोग्राम विंडोज या लिनक्स के तहत चलता है, जिसमें एक सॉर्ट प्रोग्राम होता है। यह इनपुट फ़ाइल की प्रत्येक पंक्ति को पढ़कर और प्रत्येक पंक्ति में 4 वर्णों, एक 2-अंकीय महीने की संख्या और एक 2-अंकीय दिन संख्या (महीनों के बीच की रिक्त रेखा के लिए दिन संख्या के रूप में '99' का उपयोग करता है) को जोड़कर काम करता है। यह महीने के सभी जन्मदिनों का पालन करता है)। यह फिर इन संशोधित लाइनों को सॉर्ट प्रोग्राम में पाइप करता है और पाइप किए गए आउटपुट को पहले 4 वर्णों को हटाने के लिए और फ़ाइल को स्थान में फिर से लिखने के लिए संसाधित करता है, जिसका अर्थ है कि आप चलने से पहले फ़ाइल का बैकअप बनाना चाहते हैं। ऐसा तब होता है जब कंप्यूटर प्रसंस्करण के बीच में ही नीचे चला जाता है। आउटपुट को एक अलग फ़ाइल में लिखने के लिए कोड को संशोधित करना बहुत मुश्किल नहीं होना चाहिए।

इस तकनीक का उपयोग किया जाता है क्योंकि फ़ाइल के आकार पर कोई धारणा नहीं बनाई जाती है - किसी दिए गए महीने में लाखों जन्मदिन हो सकते हैं। जब तक सॉर्ट प्रोग्राम इनपुट को हैंडल कर सकता है, यह प्रोग्राम कर सकता है।

from subprocess import Popen, PIPE
import sys
import re

p = Popen('sort', stdin=PIPE, stdout=PIPE, shell=True, text=True)
month_no = 0
with open('test.txt', 'r+') as f:
    for line in f:
        if " birthdays:**" in line:
            month_no += 1
            p.stdin.write("%02d00" % month_no)
        else:
            m = re.match(r'\*\*(\d+)\*\*', line)
            if m:
                p.stdin.write("%02d%02d" % (month_no, int(m[1])))
            else:
                # blank line?
                p.stdin.write("%02d99" % month_no)
        p.stdin.write(line)
    p.stdin.close()
    f.seek(0, 0) # reposition back to beginning
    for line in p.stdout:
        f.write(line[4:]) # skip over
    f.truncate() # this really shouldn't be necesssary
p.wait()
1
Booboo 27 जिंदा 2021, 00:19

collections.defaultdict का उपयोग करना यहां बहुत आसान होगा इसलिए आपको कोई जांच करने की आवश्यकता नहीं है आप केवल डेटा जोड़ सकते हैं। आप मूल रूप से वर्तमान माह को एक चर में रखते हुए फ़ाइल को पढ़ते हैं और जांचते हैं कि आप एक नए महीने पर हैं या नहीं, यदि आप एक नए महीने पर हैं तो बस इसे अपडेट करें, यदि आप किसी तिथि पर हैं तो दिन प्राप्त करें और संलग्न करें डोर। (इससे एक से अधिक लोगों का एक ही जन्मदिन हो सकता है।

from collections import defaultdict

data = defaultdict(lambda: defaultdict(list))

with open('filename.txt') as infile:
    month = next(infile).strip()
    for line in infile:
        if not line.strip(): continue
        if line[2].isalpha():
            month = line.strip()
        else:
            data[month][int(line.split('**')[1])].append(line.strip())

यह आपको अपने उदाहरण के आधार पर नीचे दिखाए गए अनुसार डेटा को बड़े करीने से प्राप्त करता है:

{'**January birthdays:**': {17: ['**17** - !@Mark'], 4: ['**4** - !@Jan'], 15: ['**15** - !@Ralph']},
 '**February birthdays:**': {27: ['**27** - !@Steve'], 19: ['**19** - !@Bill'], 29: ['**29** - !@Bob']}}

यहां से आप डेटा के माध्यम से वापस लूप करते हैं और जैसे ही आप लूप करते हैं और फ़ाइल में लिखते हैं, वैसे ही तिथियों को सॉर्ट करें।

with open('filename.txt', 'w') as outfile:
    for month, days in data.items():
        outfile.write(month + '\n')
        for day in sorted(days):
            for day_text in days[day]:
                outfile.write(day_text + '\n')
        outfile.write('\n')
0
Jab 27 जिंदा 2021, 00:20