Klasör arama algoritması

oy
0

Bu Buralarda sorulan alır, ya da ben buna herhangi bir cevap almak, ama edersiniz eğer bir klasör yapısı içeren görüntüden DB bağlayan kayıtları üreten bir sözde kod yaklaşımı arıyorum sorunun zamanki tür emin değilim Dosyalar.

Ben gruplanmışbilgiler aşağıdaki şekilde yapılandırılmış klasörler, bir dizi var:

+-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
  ...  ... ...  

Özünde, 1999 yılında başlayan yıl araçlar için olası görüntüleri temsil eder.

Yapar ve modelleri (örn olun: Alfa Romeo, Model: 145), çeşitli süsler veya modelleri mevcut. Her Döşeme, veya sürüm aynı görünüyor ama yakıt türü veya motor kapasitesi farklılıkları söylemek zorunda kalacak bir sayı araç bulunabilir.

tekrarını kaydetmek için klasör yapısı üzerinde bir varsayılan klasör kullanır ... Ve görüntüleri itibaren 2000 varsayılan sürümü için görünür. kendi ağır basan resimlere sahip olmasına bağlı veya varsayılan versiyonunun yapmak kullanımı olsun ... - Ben her sürümü için bağlantılar tablosunu üretmek gerekir

Yani, örneğin, VERSION_1 hiçbir görüntü dosyaları vardır, bu yüzden varsayılan görüntüler, 2000 yılında başlayan ve 2009 yılına kadar devam etmek için bağlantılar yapmak gerekir.

Öte yandan Versiyon 2 2000 yılında varsayılan görüntüleri kullanılarak başlar, ancak daha sonra 2001-2002 için ilk iki yeni setleri kullanır ve daha sonra 2003-2009. Gerekli bağlantıları listesi bu nedenle vardır ...

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
...

(- bir yer tutucu ve hiçbir bağlantıları bunun için gerekli olan Standart sadece budur.)

Şu anda, klasörler arasında çalışan dizileri bina ve ardından sonunda yağ buduyorum. metin işleme yaklaşımı çeşit kullanarak, kestirme olsaydı ben sadece merak ediyorum? Boş :-) bunların çoğu yaklaşık 45.000 klasörleri vardır

Oluştur 05/07/2009 saat 21:43
kaynak kullanıcı
Diğer dillerde...                            


1 cevaplar

oy
1

İşte yürütülebilir oldukça yakın bazı Python yalancı kod, var (gerçek yazma yapacak bir writerow fonksiyonu için uygun ithalat ve def gerekiyor - bir ara dosyaya, DB, CSV ne olsun):

# 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)

spec ve örnekteki Bir belirsizlik default_version bazı yıllarda dosyaları kümesini değiştirmek için bu mümkün olup olmadığıdır - burada, bunu sadece belirli sürümleri şeklini değiştirse (olmaz sanıyorum, varsayılan sürümü daima bir set taşır dosyaların).

Bu durum söz konusu değilse, ne olur ise 2001 ve 2005 yılında yılda varsayılan sürümü değişiklikleri (diyelim ki) 1999 ve 2003 ve version1 değişiklikleri - hangi dosyaların gerektiği 03 ve 04, varsayılan versiyonu yenilerini sürüm 1 kullanım veya bu o 01 de belirtilen?

Spec en karmaşık versiyonunda (burada default_version ve öncelik alarak son değişiklikle, değiştirebilir belirli bir, ve her ikisi de aynı yıl içinde hem özel ve varsayılan değişim daha sonra belirli alma önceliği ise) bir bütün alması gerekiyor "bir sonraki değişim yılı" dizisi, her özel sürümü için dikkatli varsayılan ve spesifik sürümü için değişim yılı dizilerin "öncelik birleştirilmesi" yerine sadece kullanarak yearsburada olduğu gibi (özel versiyonda değişikliklerin dizisi) - ve sırayla yerleştirilir her bir değişiklik sene elbette dosyaların uygun kümesiyle ilişkilendirilmesi gerekir.

Kesin Spec ifade edin eğer Yani, aşağı köşe durumlarda, bu pseudocode değiştirerek gerekli birleştirme nasıl gösterebiliriz - Ben işi oldukça istemiyorsanız tam gözlük, çünkü eğer açıklık kadar gözlük gerçekten basittir, iş gereksiz olurdu! -)

Düzenleme : yeni bir yorum açıklık olarak, tam gözlük aslında en karmaşık biridir, bu yüzden var uygun birleştirme do. Değişikliklerin yukarıdaki basit cevabın sonunda döngü Yani:

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)

Anahtar değişimdir merged = dict(...hattı: Python, bu (dict genellikle diğer dillerde bir HashMap aranmak, genel bir eşleme olduğu) hangi toplamıdır veya birleştirme, yeni bir dicti birleştirilmiş yapmak demektir default_versionve years_dict, ama ne zaman bir anahtar, bu her iki mevcuttur, gelen değer years_dicthem de (yani dosyalarda bir değişiklik ile bir yıl) hediyesi bir yıl boyunca şart olarak karşılar - önceliklidir.

Bundan sonra kısmıydı verilmiştir: anydict.pop (somekey) anahtarına karşılık gelen bir değer verir (ve ayrıca anydict kaldırır); dak (anydict) sözlükte asgari anahtarı döndürür. Kısmındaki "Sentinel" deyim Not merged[max_year + 1] = None: satır son ayarlanan her zaman düzgün yazılmasını sağlayacak şekilde bu yıl "max biri ardına" her zaman (Yok bir kukla tutucu değeriyle) bir değişiklik yıllık olarak kabul söylüyor (maksimum yıla max_year + 1 - 1, tam olarak bir, max_yeararzu edildiği gibi).

Bu algoritma, sadece basit maksimum verimli değildir! Biz yapıyoruz min(merged)O (N karesi) yapma, tekrar tekrar - Sanırım her çünkü göze düşünüyorum mergeden fazla birkaç düzine değişiklik-yıl var, ancak gereken saf ırka çekinme olacaktır. Biz tabii bir O (N logn) çözümü sunabilir - sadece bir kez ve tüm yıl sıralamak ve ardışık değerlerini almak için bu diziyi yürümek next_change. Sadece şeyiyle ...:

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

İşte sortedanahtarlarını içeren bir liste verir mergedsıralanmış sırayla, ben geçiş yaptıktan forbaşından sonuna kadar o listeyi yürümeye açıklamada (ve bir eğer çıkış hiçbir şey ifadeleri aracılığıyla ilk kez). Sentinel şimdi default_version koymak (yani başka bir hafif optimizasyonu için, döngü dışında bulunuyor) olan. Bu duruma getirilmiş sürümü (aslında bu soyutlama biraz daha yüksek bir seviyede çalıştığı için) öncekilerin ;-) daha küçük ve daha basit olarak çıkıyor görmek komik.

Cevap 05/07/2009 saat 22:57
kaynak kullanıcı

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