फ़ोल्डर खोज एल्गोरिथ्म

वोट
0

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

मैं फोल्डर, folllows के रूप में संरचित का एक सेट है:

+-make_1/
  | +--model_1/
  |    +-default_version/
  |    |   +--1999
  |    |   +--2000
  |    |   |   +--image_01.jpg
  |    |   |   +--image_02.jpg
  |    |   |   +--image_03.jpg
  |    |   |   ...
  |    |   +--2001
  |    |   +--2002
  |    |   +--2003
  |    |   ...
  |    |   +--2009
  |    +--version_1/
  |    |   +--1999
  |    |   ...
  |    |   +--2009
  |    +--version_2/
  |    |   +--1999
  |    |   +--2000
  |    |   +--2001
  |    |   |   +--image_04.jpg
  |    |   |   +--image_05.jpg
  |    |   |   +--image_06.jpg
  |    |   |   ...
  |    |   +--2002
  |    |   +--2003
  |    |   |   +--image_07.jpg
  |    |   |   +--image_08.jpg
  |    |   |   +--image_09.jpg
  |    |   ...
  |    |   +--2009
  ...  ... ...  

संक्षेप में, यह 1999 में शुरू होने वाले वाहनों के लिए संभव छवियों, साल से प्रतिनिधित्व करता है।

बनाता है और मॉडलों (जैसे बनाओ: अल्फा रोमियो, मॉडल: 145) विभिन्न ट्रिम्स या संस्करणों में आते हैं। प्रत्येक ट्रिम, या संस्करण वाहनों जो एक ही लग रही है लेकिन ईंधन के प्रकार या इंजन क्षमता में मतभेद कहना होगा की एक संख्या में पाया जा सकता है।

दोहराव बचाने के लिए, फ़ोल्डर संरचना के ऊपर एक डिफ़ॉल्ट फ़ोल्डर का उपयोग करता है ... और छवियों 2000 से अबतक से डिफ़ॉल्ट संस्करण के लिए दिखाई देते हैं। मैं प्रत्येक संस्करण के लिए लिंक तालिका उत्पादन की जरूरत है - अपने स्वयं के अधिभावी छवियों है या नहीं के आधार पर, या क्या डिफ़ॉल्ट संस्करण का उपयोग करें ...

उदाहरण के लिए, VERSION_1 कोई छवि फ़ाइलें है, तो मैं डिफ़ॉल्ट छवियों, 2000 में शुरू करने और 2009 तक जारी रखने के लिए के लिए लिंक बनाने की जरूरत है।

दूसरी ओर संस्करण 2 2000 में डिफ़ॉल्ट छवियों का उपयोग कर बाहर शुरू होता है, लेकिन फिर 2001-2002 के लिए पहले दो नए सेट का उपयोग करता है, और फिर 2003-2009। आवश्यक लिंक की सूची इसलिए कर रहे हैं ...

version    start     end   file_name
=======    =====   =====   =========
version_1   2000    2009   image_01.jpg
version_1   2000    2009   image_02.jpg
version_1   2000    2009   image_03.jpg
...
version_2   2000    2001   image_01.jpg
version_2   2000    2001   image_02.jpg
version_2   2000    2001   image_03.jpg
version_2   2001    2003   image_04.jpg
version_2   2001    2003   image_05.jpg
version_2   2001    2003   image_06.jpg
version_2   2003    2009   image_07.jpg
version_2   2003    2009   image_08.jpg
version_2   2003    2009   image_09.jpg
...

(डिफ़ॉल्ट सिर्फ इतना है कि है - एक स्थान धारक है, और कोई लिंक इसके लिए आवश्यक हैं।)

फिलहाल मैं फ़ोल्डरों के माध्यम से चल रहा हूँ, सरणियों के निर्माण, और फिर अंत में वसा ट्रिमिंग। मैं सिर्फ अगर वहाँ एक ही समाप्त हो गया, पाठ प्रसंस्करण दृष्टिकोण के कुछ प्रकार का उपयोग कर सोच रहा था? वहाँ लगभग 45,000 फ़ोल्डरों, जिनमें से अधिकांश खाली :-) हैं

05/07/2009 को 21:43
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


1 जवाब

वोट
1

यहाँ कुछ अजगर स्यूडोकोड, सुंदर निष्पादन के काफी करीब है (उपयुक्त आयात और एक writerow समारोह है कि वास्तविक लेखन करना होगा के लिए एक डीईएफ़ की जरूरत है - एक मध्यवर्ती फाइल करने के लिए ठीक है, डीबी, सीएसवी, जो कुछ भी):

# first, collect all the data in a dict of dicts of lists
# first key is version, second key is year (only for non-empty years)

tree = dict()
for root, dirs, files in os.walk('make_1/model_1'):
    head, tail = os.path.split(root)
    if dirs:
       # here, tail is a version
       tree[tail] = dict
    elif files:
       # here, tail is a year
       tree[os.path.basename(head)][tail] = files

# now specialcase default_version
default_version = tree.pop('default_version')
# determine range of years; rule is quite asymmetrical:
#   for min, only years with files in them count
min_year = min(d for d in default_version if default_version[d])
#   for max, all years count, even if empty
max_year = max(default_version)

for version, years in tree.iteritems():
    current_files = default_version[min_year]
    years.append(max_year + 1)
    y = min_year
    while years:
        next_change = min(years)
        if y < next_change:
            for f in current_files:
                writerow(version, y, next_change-1, f)
        y = next_change
        current_files = years.pop(y)

कल्पना और उदाहरण में एक अस्पष्टता है कि क्या यह संभव है default_version कुछ वर्षों में फ़ाइलों का सेट बदलने के लिए है - यहाँ, मुझे लगता है कि ऐसा नहीं होता है (केवल विशिष्ट संस्करणों कि जिस तरह से बदल संभालने हूँ, डिफ़ॉल्ट संस्करण हमेशा एक सेट किया जाता है फ़ाइलों की)।

अगर ऐसा नहीं है, तो क्या होता है के वर्षों में डिफ़ॉल्ट संस्करण परिवर्तन (माना) 1999 और 2003, और version1 परिवर्तन 2001 और 2005 में - क्या फ़ाइलों चाहिए संस्करण 1 03 और 04, डिफ़ॉल्ट संस्करण में नए लोगों के लिए उपयोग , या उन यह 01 में निर्दिष्ट?

कल्पना का सबसे जटिल संस्करण में (जहां दोनों default_version और एक विशिष्ट एक सबसे हाल ही में पूर्वता ले जा रहा परिवर्तन के साथ, बदल सकते हैं और एक ही वर्ष में दोनों विशिष्ट और डिफ़ॉल्ट परिवर्तन तो विशिष्ट लेने पूर्वता यदि) एक सब होने की जरूरत है "अगले परिवर्तन साल" अनुक्रम, प्रत्येक विशिष्ट संस्करण के लिए, डिफ़ॉल्ट और विशेष संस्करण के लिए वर्ष परिवर्तन के दृश्यों से सावधान "प्राथमिकता विलय", के बजाय सिर्फ का उपयोग करके years(विशिष्ट संस्करण में परिवर्तन के अनुक्रम) के रूप में मैं यहाँ करते हैं - और प्रत्येक परिवर्तन साल अनुक्रम में रखा निश्चित रूप से फ़ाइलों की उचित समूह के साथ जुड़ा होना चाहिए।

तो अगर सटीक कल्पना व्यक्त किया जा कृपया कर सकते हैं, कोने मामलों के लिए नीचे, मैं कैसे इस स्यूडोकोड को संशोधित करने की जरूरत विलय करने के लिए दिखा सकते हैं - मैं काम करने के बजाय नहीं चाहते हैं जब तक सटीक चश्मा स्पष्ट किया जाता है, क्योंकि, अगर चश्मा वास्तव में आसान है, काम अनावश्यक होगा -!)

संपादित करें : के रूप में एक नई टिप्पणी को स्पष्ट किया, सटीक चश्मा वास्तव में सबसे अधिक जटिल एक है, तो हम उचित रूप से विलय कर करते हैं। तो में परिवर्तन ऊपर साधारण जवाब के अंत में पाश:

for version, years_dict in tree.iteritems():
    # have years_dict override default_version when coincident
    merged = dict(default_version, **years_dict)
    current_files = merged.pop(min_year)
    merged[max_year + 1] = None
    y = min_year
    while merged:
        next_change = min(merged)
        for f in current_files:
            writerow(version, y, next_change-1, f)
        y = next_change
        current_files = merged.pop(y)

कुंजी परिवर्तन है merged = dict(...लाइन: अजगर में, इसका मतलब है एक नया dict (एक dict एक सामान्य मानचित्रण, आम तौर पर अन्य भाषाओं में एक hashmap कहा जा सकता है है), जो, योग है, या मर्ज का विलय कर दिया करने के लिए बनाते हैं default_versionऔर years_dictहै, लेकिन जब एक कुंजी उन दोनों में मौजूद है, से मूल्य years_dictजो एक साल कि (यानी, फ़ाइलों में परिवर्तन के साथ एक वर्ष है) मौजूद है दोनों में के लिए महत्वपूर्ण शर्त पूरी करता है - प्राथमिकता मिलती है।

उसके बाद यह सादे नौकायन है: anydict.pop (somekey) कुंजी करने के लिए इसी मान देता है (और यह भी anydict से निकालता है); मिनट (anydict) शब्दकोश में न्यूनतम कुंजी देता है। पर नोट "प्रहरी" मुहावरा merged[max_year + 1] = None: इस का कहना है कि साल "अधिकतम एक के बाद एक" हमेशा एक परिवर्तन साल (कोई नहीं के एक डमी प्लेसहोल्डर मूल्य के साथ) माना जाता है ताकि पंक्तियों के अंतिम सेट हमेशा ठीक से लिखा है (की एक अधिकतम साल के साथ max_year + 1 - 1, कि है, वास्तव में max_year, के रूप में आवश्यक होने पर)।

इस एल्गोरिथ्म अधिकतम कुशल, सिर्फ आसान नहीं है! हम कर रहे हैं min(merged)अधिक से अधिक है, यह हे (एन चुकता) बनाने - मुझे लगता है कि हम बर्दाश्त कर सकते हैं कि क्योंकि प्रत्येक mergedज्यादा से ज्यादा कुछ दर्जन परिवर्तन साल होना चाहिए, लेकिन एक शुद्धतावादी wince जाएगा। हम निश्चित रूप से पेश कर सकते हैं एक हे (एन logn) समाधान - बस एक बार और सभी के लिए साल सॉर्ट और उस क्रम चलना के लिए लगातार मूल्यों को प्राप्त करने के लिए next_change। बस संपूर्णता के लिए ...:

default_version[max_year + 1] = None

for version, years_dict in tree.iteritems():
    merged = dict(default_version, **years_dict)
    for next_change in sorted(merged):
        if next_change > min_year:
            for f in merged[y]:
                writerow(version, y, next_change-1, f)
        y = next_change

यहाँ sortedकी कुंजी के साथ एक सूची प्रदान करती mergedक्रमबद्ध क्रम में, और मैं अपना ली है for(और एक करता है, तो उत्पादन कुछ भी नहीं करने के लिए बयान पहली बार के माध्यम से) बयान समाप्त करने के लिए शुरू से ही उस सूची चलने के लिए। प्रहरी अब default_version में डाल दिया जाता है (इसलिए यह पाश के बाहर है, एक और मामूली अनुकूलन के लिए)। यह देखने के लिए कि यह अनुकूलित संस्करण (अनिवार्य रूप से, क्योंकि यह अमूर्त की एक से थोड़ा अधिक स्तर पर काम करता है) छोटे और पिछले अभियानों ;-) से सरल होने के लिए पता चला है मज़ेदार है।

05/07/2009 को 22:57
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more