2010-09-07 8 views
9

bir Data.Vector.Generic.Mutable nesne ve Verilerden bir tür algoritma kullanarak büyük bir dosyada (milyon diyelim ki birkaç satır) okunur ki (dizeleri, vs yüzer). Vector.Algorithms?Data.Vector.Generic.Mutable ile nasıl bir sıralama yapar? Verilerin bir uzun listesini sıralamak nasıl

+0

, Data.Vector.Generic.Mutable bir amacı değildir, herhangi bir tür işlemler için soyut API'dır değişken vektör. Bunlar Data.Vector.Unboxed.Mutable, Data.Vector.Storable.Mutable, vb içerir – jrockway

cevap

16

Burada genel durumda bunu yapmak için nasıl.

Önce, bir değişken vektörü gerekir. Bu dosyayı adım adım olarak tarayabilirsiniz; İhtiyacınız kadar büyük olan bir vektör tahsis edin, ve alanınızı azalttığınızda boyutu artırın ve kopyalayın. Yoksa , dosyanın tamamını okumak rekor ayırıcılar saymak ve tek seferde alan doğru miktarda ayırabilirsiniz. Bu daha kolay ama muhtemelen Real Life'da kabul edilemez. (Genişletmek-olarak ihtiyaç duyulan strateji oldukça yaygındır; Hiç Perl gibi bir dil kullanmak ve bir dizinin sonuna üzerine bir dosyadan size okumak hatları zorlarsan, bu şey bu Perl bir dizi için biraz boşluk ayırır. , bunu doldururken, bu alan miktarını artırır yeni bir alan ve kopyalarını ayırır.)

Neyse, bu yapamayacak kadar tembelim, bu yüzden sadece bazı rastgele bir vektör oluşturmak için gidiyorum içindeki sayılar. Biz tek seferde buna ihtiyacım yok, ama biz sonunda gerekir

import Control.Monad 
import System.Random 
import qualified Data.Vector as IV 
import qualified Data.Vector.Mutable as MV 
import qualified Data.Vector.Generic as V 
import qualified Data.Vector.Algorithms.Intro as VA 

, bu yüzden ben dışına almak düşündüm:

Bunun için kütüphanelerin bir demet ihtiyaç yol. Neyse, bizim değişebilir vektörümüz MV.MVector " " şeklinde bir "normal" değişken vektör olacaktır.

kesilebilir bir vektör fikri

bunu oluşturmak ve adımlar sayısında değişiklik olması. Haskell'de, bu kodu arama koduna göre düzeltmek için birkaç yol vardır; Bunlardan biri ST monad içinde yapılıyor. ST eyleminiz vektörü oluşturuyor, değiştiriyor ve 'u "değişmez" bir vektöre "donduruyor". Dahili olarak, değiştirmek-bu-hafıza-yeri-a-demet-of-the zamanlarda işlemlerini hızlı kullanıyor, ancak dışarıdan, saf bir şey var. (Eğer bu güvenlidir neden olarak bir tartışmayı istiyorsanız kağıdı yaklaşık ST okuyun.)

değişken veri ile başa çıkmak için başka bir yolu da Herşey içeride bunu sadece üzere, şey, IO, monad olduğunu. Burada yapacağımız şey bu, en uygunudur.

(Data.Vector.Mutable sizin için önceden tanımlanmış iki vektör tipleri, IOVector ve STVector sahiptir. Biz IO içine tüm vektör işlemlerini koyar IOVector kullanıyorsunuz.)

Yani 8 gibi paragraflar önce, gittiğini sort için bir değişken vektör oluşturun. Ve işte buradayız:

randVector :: IO (MV.IOVector Int) 
randVector = do 
    v <- MV.new 10 
    forM [0..9] $ \x -> do 
    r <- randomIO :: IO Int 
    MV.write v x r 
    return v 

Bu İçinde 10 rasgele sayılarla yeni değişken vektörü döndüren bir IO eylemdir.(Rastgele sayı üretme da rahatlıkla IO monad içine kaldırdı olabilir, bu nedenle kolaylık, bu çok yaptı! Biz ancak güzel sözdizimi ve daha tip güvenliği ile C yazıyorsunuz bu.)

aslında o zor bölüm. Sıralama yapmak için, temel olarak yerinde bir quicksort olan Data.Vector.Algorithms.Intro'u içe aktardım. sort adlı bir işlev, gerçek sıralama yapar ( 'da, değiştirilebilen vektörün hangisi olduğu).

rastgele değişken vektörü oluşturur ve yerinde bunu sıralar bir eylem benziyor: O yazdırmak için Şimdi

sort = VA.sort =<< randVector 

, biz bir iletmenin içine vektörü "dondurmak" yapmanız gereken tüm ve .toList'u yazdırın. Ya da sadece her elemanın üzerine yineleyebilir ve yazdırabilirsiniz.

Burada bir örnek olarak geldi ne:

main = do 
    v <- randVector 
    VA.sort v 
    iv <- V.unsafeFreeze v :: IO (IV.Vector Int) 
    print . V.toList $ iv 

V.unsafeFreezeData.Vector.Generic kaynaklıdır (sen nasıl etkileşimde aynı API ile tüm vektör türler), V.toList olduğu gibi. Her neyse, IO'nun burada kolaylık sağlamak için olduğunu da belirtmek gerekir. Dosya verisinden bir vektör oluşturduğunuzdan, uygun. Zamanın% 99 , ST kullanmanız gerekir. ST işleminizde, vektörünü oluşturun, sıralayın, dondurun ve donmuş sürümü döndürün.

benzer bir örnek STVector kullanılarak:

randVector :: ST s (Vector Int) 
randVector = do 
    vec <- new 10 
    rand <- newSTRef 17 
    forM_ [0..9] $ \index -> do 
    randN <- readSTRef rand 
    let randN' = (fst . next . mkStdGen) randN 
    writeSTRef rand randN' 
    write vec index randN' 
    unsafeFreeze vec 

sonra çalıştırmak: Ayrıca

*Main> runST randVector 
fromList [679560,1422110406,306332632,1905242129,692062628,393451229,355476175,1240028023,873588529,1181443777] :: Data.Vector.Vector 
+0

Yardım jrockway için teşekkürler. IO monadından rahatım ama açıkçası ST monad'ı öğrenmem gerek. Örnek kodunuzu çalıştırdıktan sonra, rastgele sayılar yerine vektörü yüklemek için bir dosyadan okumak için değiştirmeye çalışacağım. – Max

+0

Teşekkürler, teşekkür ederim teşekkürler. Genel kullanıma iyi örneklerle ST'ye çok hoş geldiniz. – Benjamin

İlgili konular