गति के लिए तार की पार्स सूची

Nov 30 2020

पृष्ठभूमि

मेरे पास एक फ़ंक्शन है जिसे get_player_pathस्ट्रिंग्स player_file_listऔर एक इंट वैल्यू की सूची में लिया जाता है total_players। उदाहरण के लिए मैंने स्ट्रिंग्स की सूची को कम कर दिया है और बहुत कम संख्या के लिए अंतर मूल्य भी निर्धारित किया है।

player_file_listया तो प्रत्येक स्ट्रिंग में एक year-date/player_id/some_random_file.file_extensionया हैyear-date/player_id/IDATs/some_random_number/some_random_file.file_extension

मुद्दा

मैं यहाँ प्राप्त करने के लिए अनिवार्य रूप से कोशिश कर रहा हूँ, इस सूची से गुजरना है और year-date/player_idएक सेट में सभी अद्वितीय पथ को तब तक संग्रहीत करना है जब तक कि यह लम्बाई के मूल्य तक न पहुँच जाएtotal_players

मेरा वर्तमान दृष्टिकोण मुझे सबसे अधिक कुशल नहीं लगता है और मैं सोच रहा हूं कि क्या मैं किसी get_player_pathभी तरह से अपने कार्य को गति दे सकता हूं ??

कोड

def get_player_path(player_file_list, total_players):
    player_files_to_process = set()
    for player_file in player_file_list:
        player_file = player_file.split("/")
        file_path = f"{player_file[0]}/{player_file[1]}/"
        player_files_to_process.add(file_path)
        if len(player_files_to_process) == total_players:
            break
    return sorted(player_files_to_process)


player_file_list = [
    "2020-10-27/31001804320549/31001804320549.json",
    "2020-10-27/31001804320549/IDATs/204825150047/foo_bar_Red.idat",
    "2020-10-28/31001804320548/31001804320549.json",
    "2020-10-28/31001804320548/IDATs/204825150123/foo_bar_Red.idat",
    "2020-10-29/31001804320547/31001804320549.json",
    "2020-10-29/31001804320547/IDATs/204825150227/foo_bar_Red.idat",
    "2020-10-30/31001804320546/31001804320549.json",
    "2020-10-30/31001804320546/IDATs/123455150047/foo_bar_Red.idat",
    "2020-10-31/31001804320545/31001804320549.json",
    "2020-10-31/31001804320545/IDATs/597625150047/foo_bar_Red.idat",
]

print(get_player_path(player_file_list, 2))

उत्पादन

['2020-10-27/31001804320549/', '2020-10-28/31001804320548/']

जवाब

PedroLobito Nov 30 2020 at 21:08

मैं इस समाधान को यहाँ छोड़ दूँगा जिसे और बेहतर बनाया जा सकता है, आशा है कि यह मदद करेगा।

player_file_list = (
    "2020-10-27/31001804320549/31001804320549.json",
    "2020-10-27/31001804320549/IDATs/204825150047/foo_bar_Red.idat",
    "2020-10-28/31001804320548/31001804320549.json",
    "2020-10-28/31001804320548/IDATs/204825150123/foo_bar_Red.idat",
    "2020-10-29/31001804320547/31001804320549.json",
    "2020-10-29/31001804320547/IDATs/204825150227/foo_bar_Red.idat",
    "2020-10-30/31001804320546/31001804320549.json",
    "2020-10-30/31001804320546/IDATs/123455150047/foo_bar_Red.idat",
    "2020-10-31/31001804320545/31001804320549.json",
    "2020-10-31/31001804320545/IDATs/597625150047/foo_bar_Red.idat",
)

def get_player_path(l, n):
  pfl = set()
  for i in l:
    i = "/".join(i.split("/")[0:2])
    if i not in pfl:
      pfl.add(i)
    if len(pfl) == n:
      return pfl

  
  if n > len(pfl):
    print("not enough matches")
    return

print(get_player_path(player_file_list, 2))
# {'2020-10-27/31001804320549', '2020-10-28/31001804320548'}

पायथन डेमो

1 janluke Nov 30 2020 at 22:25

आइए पहले अपने फ़ंक्शन का विश्लेषण करें:

  • आपके लूप को इनपुट सूची की लंबाई में रैखिक समय (O (n)) लेना चाहिए, यह मानते हुए कि पथ की लंबाई अपेक्षाकृत "छोटी" संख्या से बंधी हुई है;
  • छँटाई में O (n log (n)) तुलना होती है।

इस प्रकार जब सूची बड़ी हो जाती है तो छंटनी की प्रमुख लागत होती है। आप जितना चाहें उतना अपने लूप को माइक्रो-ऑप्टिमाइज़ कर सकते हैं, लेकिन जब तक आप अंत में उस तरह की छँटाई करते रहेंगे, तब तक आपके प्रयास से बड़ी सूचियों पर कोई फर्क नहीं पड़ेगा।

यदि आप सिर्फ पायथन स्क्रिप्ट लिख रहे हैं तो आपका दृष्टिकोण ठीक है। यदि आपको वास्तव में विशाल सूचियों के साथ सुगंध की आवश्यकता है, तो आप शायद किसी अन्य भाषा का उपयोग कर रहे हैं। फिर भी, यदि आप वास्तव में प्रदर्शन के बारे में परवाह करते हैं (या सिर्फ नया सामान सीखना है), तो आप निम्नलिखित तरीकों में से एक का प्रयास कर सकते हैं:

  • स्ट्रिंग के लिए कुछ विशिष्ट के साथ सामान्य सॉर्टिंग एल्गोरिथ्म को बदलें; उदाहरण के लिए यहाँ देखें
  • छँटाई की आवश्यकता को दूर करते हुए, एक ट्राइ का उपयोग करें ; यह सैद्धांतिक रूप से बेहतर हो सकता है लेकिन व्यवहार में शायद बदतर है।

पूर्णता के लिए, एक माइक्रो-ऑप्टिमाइज़ेशन के रूप में, यह मानते हुए कि तिथि में 10 वर्णों की निश्चित लंबाई है:

def get_player_path(player_file_list, total_players):
    player_files_to_process = set()
    for player_file in player_file_list:
        end = player_file.find('/', 12)       # <--- len(date) + len('/') + 1
        file_path = player_file[:end]         # <---
        player_files_to_process.add(file_path)
        if len(player_files_to_process) == total_players:
            break
    return sorted(player_files_to_process)

यदि आपकी उदाहरण सूची में आईडी की लंबाई भी निर्धारित है, तो आपको किसी विभाजन या खोजने की आवश्यकता नहीं है: बस

LENGTH = DATE_LENGTH + ID_LENGTH + 1   # 1 is for the slash between date and id
...
for player_file in player_file_list:
    file_path = player_file[:LENGTH]
...

EDIT: LENGTHइनिशियलाइज़ेशन तय किया, मैं 1 जोड़ना भूल गया था

AajKaal Nov 30 2020 at 21:19

तानाशाही का उपयोग करें ताकि आपकी सूची पहले से छँट जाने के बाद आपको उसे छाँटना न पड़े। यदि आपको अभी भी सॉर्ट करने की आवश्यकता है तो आप हमेशा रिटर्न स्टेटमेंट में सॉर्ट किए जा सकते हैं। आयात पुनः जोड़ें और अपने फ़ंक्शन को निम्नानुसार बदलें:

def get_player_path(player_file_list, total_players):
    dct = {re.search('^\w+-\w+-\w+/\w+',pf).group(): 1 for pf in player_file_list}
    return [k for i,k in enumerate(dct.keys()) if i < total_players]