2017-09-15 62 views
2

我需要爲兩個代碼列表生成大量的唯一代碼,這兩個代碼不能相互匹配並且是唯一的代碼。 它必須是七個字符的長度。在Ruby中生成很多獨特的令牌

但是我不滿意我的最終解決方案,我不得不讓整個晚上都跑步。

  • 我也喜歡使用一組(因爲集比陣列更快),但我不能設定所選擇的索引在像我可以與陣列分成兩個部分。

  • 我想要並行化令牌創建,但它會暗示要管理共享代碼數組以檢查唯一性以及所涉及的所有鎖定問題。

這裏是我使用的代碼:

# n is the token length, quantity the number of tokens I want. 
def gen_codes(n=7, quantity=10) 
    tokens = [] 
    quantity.times do |q| 
    token = [*('a'..'z'), *('A'..'Z'), *(0..9)].sample(7).join 
    while tokens.include?(token) 
     token = [*('a'..'z'), *('A'..'Z'), *(0..9)].sample(7).join 
    end 
    tokens << token 
    end 
    tokens 
end 

CODES1 = 750e3.to_i 
CODES2 = 250e3.to_i 

puts "Generating codes" 

codes = gen_codes(7, CODES1+CODES2) 
codes2 = codes[0, CODES2] 
codes1 = codes[CODES2, CODES1] 

File.open('codes1.txt', 'w+') do |f| 
    f.puts codes1 
end 

File.open('codes2.txt', 'w+') do |f| 
    f.puts codes2 
end 

有沒有人有一個更好的解決方案?

+0

你說「lot」有多少? –

+0

也使用二進制搜索,而不是包括?這是O(n)時間複雜度。您可以使用二進制搜索[此處]檢查重複(https://ruby-doc.org/core-2.4.1/Array.html#method-i-bsearch) –

回答

4

這應該工作:

require 'set' 

alphabet = [*('a'..'z'), *('A'..'Z'), *(0..9)] 

CODES1 = 750_000 
CODES2 = 250_000 

set = Set.new 
set << alphabet.sample(7).join until set.size == CODES1 + CODES2 
codes = set.to_a 

codes1 = codes[0...CODES1] 
codes2 = codes[CODES1..-1] 

File.write('codes1.txt', codes1) 
File.write('codes2.txt', codes2) 

注意到我的系統上約4秒。

+2

使用'Set'來避免檢查唯一性是一個非常低估的漂亮技巧,不是嗎? – mudasobwa

+1

@mudasobwa或者'value => true'對的'Hash'。 (其中'Set'可能在引擎蓋下,沒有檢查) – Stefan

0

如果在令牌中有A-Z, a-z, 0-9, 「+」, 「/」 and 「=」是可以接受的,則可以使用SecureRandom。它的快速和隨機:

require 'set' 
require 'securerandom' 

length = 7 
total = 1_000_000 
batch = 1000 

tokens = Set.new 
(total/batch).times do 
    SecureRandom.base64(batch*length).scan(/.{#{length}}/).each do |token| 
    tokens << token 
    end 
end 

tokens現在包含約1333000獨特的標記,這是足以滿足您的需求更多。