2013-03-13 76 views
0

我試圖根據一定的長度生成隨機字符串。例如,如果length = 4,我生成從aaaa到zzzz的所有字符串。我需要以後的所有重複測試。這是我如何去做:生成字符串和內存不足

len = 5 
str = ('a'..'z').to_a.repeated_permutation(len).map(&:join) 

問題是,這是佔用大量的內存。事實上,我的程序因爲Ruby解釋器無法分配足夠的內存而終止。有沒有更少的內存密集型方式來產生這些字符串?

編輯:萊恩在技術上是一個變量。它的範圍可以從2到7.

+0

雖然這實際上對我來說工作正常,但它是一種生成456976可能字符串的非常低效的方法。您首先構建456976個字符數組,然後通過「連接」映射每個字符。你將會使用比需要更多內存和CPU的數量級。 – meagar 2013-03-13 13:27:56

+0

我第一次看到你的長度爲4。對於5個字符,您正在查看11881376個字符串,但會生成並連接第一個11881376 5元素數組。 – meagar 2013-03-13 13:36:35

回答

3

只需使用('aaaaa'..'zzzzz').to_a。它避免了將每個數字構建爲四個字母數組並將它們連接回字符串的中間步驟。

這是(在我的系統上)的四倍快,它幾乎肯定會使用一部分內存。

...問題是,len爲可變....從2至7

然後使用(('a' * len)..('z' * len)).to_a。這仍然更快,因爲唯一的臨時分配是由'a' * len'z' * len生成的字符串,其長度在4到14個字符之間。

+0

+1 Ruby每天都讓我驚喜......:) – 2013-03-13 13:29:54

+0

我應該在我的例子中更清楚,但問題是len是一個變量。 Len的範圍可以從2到7. – nizbit 2013-03-13 15:33:03

+1

那麼,用'('a'* len)..('z'* len)'來代替。 – meagar 2013-03-13 18:45:27

0

您可以一個接一個地排列排列 - 取決於您是否需要稍後批量處理它們。

所以,如果你可以喂到字符串測試一個接一個,那麼你可以做

enumerator = str = ('a'..'z').to_a.repeated_permutation(len) 
my_test(enumerator) 

和。 。 。

def my_test e 
    e.each do |string| 
    # Test it 
end 

這仍然很多,雖然過程中,我會想到這樣的代碼需要幾分鐘的時間至少要運行,你正在測試超過1100萬獨立字符串。

+0

你可以*仍然*只使用''aaaa'..''zzzz''。這裏真正的問題是使用repeat_permutation。 – meagar 2013-03-13 13:31:01

+0

是的,剛剛在IRB中嘗試過,str =('aaaaa'..'zzzzz')to_a的速度驚人。 – 2013-03-13 13:34:52

0

降低使用的內存量可以通過使用flyweight模式來實現。

我不確定您有多少時間在投資解決方案,但創建了一個類,其中有許多「字母」,它們按特定順序排列,每個字母指向一個共享池String s(對於字母表中的每個字母一個)將允許您降低內存(可以使用散列)。然後,您可以覆蓋to_s以輸出新對象,並修改repeated_permutation方法以接受您的新對象。

請注意,如果您期望len變得相當大,解決方案只值得您的時間。

+1

這可以通過爲單個字符使用符號而不是字符串來實現。 – 2013-03-13 14:09:40

+0

偉大的一點@AndrewMarshall – nattyddubbs 2013-03-13 14:12:08

0
len = 5 
(('a'*len)..('z'*len)).to_a