2011-01-07 19 views
21

Öncelikle, bu sorunu giderdim, çünkü aşağıdaki soruna bir çözüm ararken, stackoverflow'ta bir tane bulamadım. Yani, buradaki bilgi tabanına biraz eklemeyi umuyordum.Dosyaları nasıl sayısal olarak sıralarsınız?

Dizinde bazı dosyaları işlemek ve sayısal olarak sıralanacak dosyalara ihtiyacım var. Özellikle lambda deseni kullanarak - - ı sıralama hakkında bazı örnekler bulduk wiki.python.org de ve bir araya getirmeme:

#!env/python 
import re 

tiffFiles = """ayurveda_1.tif 
ayurveda_11.tif 
ayurveda_13.tif 
ayurveda_2.tif 
ayurveda_20.tif 
ayurveda_22.tif""".split('\n') 

numPattern = re.compile('_(\d{1,2})\.', re.IGNORECASE) 

tiffFiles.sort(cmp, key=lambda tFile: 
        int(numPattern.search(tFile).group(1))) 

print tiffFiles 

Hala Python oldukça yeniyim ve varsa topluluk sormak istiyorum Buna yapılabilecek iyileştirmeler: kodu kısaltmak (lambda'u kaldırmak), performans, stil/okunabilirlik?

, Zachary Bu "doğal sıralama" ya da (varsayılan sıralama lexicographical aksine,) "insan sıralama" denir

+2

+1. – systemovich

+4

Yaptığınız şeyi yapmak için _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ soru sormak için soru bitine, sonra cevabınızı cevap bitine ekleyin Ardından arkanıza yaslanın ve bekleyiniz ... – paxdiablo

+0

@paxdiablo: Talimatlar için teşekkürler ... Cevap verebildiğimden emin olmak için SSS bölümünü okudum, sadece mekanikleri hakkında tam olarak emin değildim. Bir dahaki sefere yapacağım. –

cevap

30

teşekkür ederiz. Ned B wrote up a quick version of one.

import re 

def tryint(s): 
    try: 
     return int(s) 
    except: 
     return s 

def alphanum_key(s): 
    """ Turn a string into a list of string and number chunks. 
     "z23a" -> ["z", 23, "a"] 
    """ 
    return [ tryint(c) for c in re.split('([0-9]+)', s) ] 

def sort_nicely(l): 
    """ Sort the given list in the way that humans expect. 
    """ 
    l.sort(key=alphanum_key) 

O ne yaptığını benzer, ama belki biraz daha genel.

+1

Teşekkür ederim, Daniel! Bu benim aradığım şeydi. Girdiğin bağlantıyı takip ettim ve gittiğim tavşan deliğinden aşağıya ... weeee !!! Denemenin/performansının ve (tabii ki) yeniden derlemelerin önceden derlenmesi performansıyla ilgili biraz bilgi aldım. :) –

+0

Bu liste, bir liste anlamadan ziyade bir jeneratör döndürürse işe yarayacak mı? –

+0

Negatif gömülü sayıları düzgün işlemez. – martineau

5

Sıralama yönteminizde key= kullanıyorsanız, Python'un en son sürümlerinden kaldırılmış olan cmp kullanmamalısınız. key, giriş olarak bir kayıt alan ve listenizi sıralamak istediğiniz sırayla karşılaştırılacak herhangi bir nesneyi döndüren bir işleve eşit olmalıdır. Bir lambda fonksiyonu olmak zorunda değildir ve bağımsız bir işlev olarak daha açık olabilir. Ayrıca düzenli ifadeler değerlendirmek için yavaş olabilir.

Sen gibi bir şey deneyebilirsiniz izole etmek ve dosya adının tam sayı kısmını geri dönmek için aşağıdakileri yapın: kayıt düzeni içinde

def getint(name): 
    basename = name.partition('.') 
    alpha, num = basename.split('_') 
    return int(num) 
tiffiles.sort(key=getint) 
+0

, Don teşekkür ederiz değil int şamandıra sayı dönüştürmek gerekir. Açıklamanızı çok takdir ediyorum: çok anlaşılabilir. --Zachary –

+0

@Don O'Donnell Hata aldım _AttributeError: 'tuple' nesnesinin 'split'_ özelliği yok, bu yüzden kodunuzu biraz değiştirdim: 'basename = name.partition ('. ')' Ile değiştiriyorum basename = name.split ('.') '(** Önemli! Sadece nokta olmayan dosya isimleri için çalışır **) ve alfa, num = basename.split ('_')' ile alfa, num = basename [0] .split ('_') 'Neyse, sen benim günümü yaptın. Teşekkürler! – KnightWhoSayNi

0

Bölme sonuçları

def getint(name): 
    (basename, part, ext) = name.partition('.') 
    (alpha, num) = basename.split('_') 
    return int(num) 
+0

Bunu gerçekten denedin mi? '(a, b, c) = 'ayurveda_11.tif'.split ('. '), ValueError: açmak için 2'den fazla değere ihtiyacım var' –

5

Hemen kullanın:

tiffFiles.sort(key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)]) 

, try/except dışında kullanımdan daha hızlıdır. Uygun soru başlığı için

İlgili konular