2017-04-20 45 views
3

我需要拆分在紅寶石一個字符串,它具有以下格式:如何(容易)分割字符串中紅寶石長度和也定界符

[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}] 

即它是一個生成的JavaScript數組。不幸的是,這個列表很長,我想在達到一個特定的長度後用數組元素分隔符逗號分割它,這個長度適合用代碼編輯器編輯它,但是要保持元素的完整性。例如,上面的15分割寬度的線將成爲:

[{a:1,b:2,c:3,d:4}, 
{a:5,b:6,c:7,d:8}, 
{a:9,b:10,c:11,d:12}, 
{a:13,b:14,c:15,d:16}] 

和具有32的寬度文本將是:

[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8}, 
{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}] 

除了經典的「蠻力」方法(循環,檢查}{之間的分隔符,同時增加長度,如果長度大於且發現有效分隔符,則進行拆分)是否有更多「Rubyish」解決方案?

編輯:幼稚的做法連接,絕對不會Rubyiish,因爲我沒有一個非常強的紅寶石背景:

def split(what, length) 
    result = [] 
    clength = 0 
    flag = FALSE 
    what_copy = what.to_s 
    what_copy.to_s.each_char do |c| 
    clength += 1 
    if clength > length 
     flag = TRUE 
    end 

    if c == '}' and flag 
     result << what[0 .. clength] 
     what = what[clength+1 .. -1] 
     clength = 0 
     flag = FALSE 
    end 
    end 
    pp result 
    sres = result.join("\n") 
    sres 
end 
+0

你寫的經典蠻力的方法呢? –

+0

@EricDuminil是的,問題更新 – fritzone

+0

我真的不明白這個問題在哪裏?您是否想要拆分{}中包含的數據,即。你會只有{a:1,b:2},顯然在額外的大括號中加入?其他方面,如果{}總是包含4個項目,爲什麼不用大括號將它們分組並返回1,2,3或4? – grail

回答

6

你可以使用正則表達式有:

  • 非貪婪重複至少width-2字符
  • 接着是}
  • 接着是,]的。

data = "[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}]" 

def split_data_with_min_width(text, width) 
    pattern =/
    (    # capturing group for split 
     .{#{width-2},}? # at least width-2 characters, but not more than needed 
     \}    # closing curly brace 
     [,\]]   # a comma or a closing bracket 
    ) 
    /x    # free spacing mode 
    text.split(pattern).reject(&:empty?).join("\n") 
end 

puts split_data_with_min_width(data, 15) 
# [{a:1,b:2,c:3,d:4}, 
# {a:5,b:6,c:7,d:8}, 
# {a:9,b:10,c:11,d:12}, 
# {a:13,b:14,c:15,d:16}, 
# {a:17,b:18,c:19,d:20}] 

puts split_data_with_min_width(data, 32) 
# [{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8}, 
# {a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}, 
# {a:17,b:18,c:19,d:20}] 

該方法使用split與捕獲組而不是scan因爲字符串的最後一部分可能不夠長:

"abcde".scan(/../) 
# ["ab", "cd"] 
"abcde".split(/(..)/).reject(&:empty?) 
# ["ab", "cd", "e"] 
1

喜歡這個?

2.3.1 :007 > a 
=> "[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}]" 
2.3.1 :008 > q = a.gsub("},", "},\n") 
=> "[{a:1,b:2,c:3,d:4},\n{a:5,b:6,c:7,d:8},\n{a:9,b:10,c:11,d:12},\n{a:13,b:14,c:15,d:16}]" 
2.3.1 :009 > puts q 
[{a:1,b:2,c:3,d:4}, 
{a:5,b:6,c:7,d:8}, 
{a:9,b:10,c:11,d:12}, 
{a:13,b:14,c:15,d:16}] 
=> nil 
2.3.1 :010 > 
+0

不完全是,因爲如果我想要最小長度爲32,那麼我只會得到2行。問題已更新。 – fritzone

+0

32,你的意思是第32個?因爲第二行超過了32個。 – marmeladze

+1

由於所有的提示如'2.3.1:007:>',你的代碼很難閱讀。而且,如果有人想運行你的代碼,他們不能只是剪切和粘貼。最好刪除這些提示。 –

2

代碼

def doit(str, min_size) 
    r =/
     (?:    # begin non-capture group     
     .{#{min_size},}? # match at least min_size characters, non-greedily 
     (?=\{)   # match '{' in a positive lookahead 
     |    # or 
     .+\z    # match one or more characters followed by end of string 
    )     # close non-capture group 
     /x     # free-spacing regex definition mode 
    str.scan(r) 
end 

例子

str = "[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}]" 

doit(str, 18) # same for all min_size <= 18 
    #=> ["[{a:1,b:2,c:3,d:4},", 
    # "{a:5,b:6,c:7,d:8},", 
    # "{a:9,b:10,c:11,d:12},", 
    # "{a:13,b:14,c:15,d:16}]"] 
doit(str, 19) 
    #=> ["[{a:1,b:2,c:3,d:4},", 
    # "{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},", 
    # "{a:13,b:14,c:15,d:16}]"] 
doit(str, 20) 
    #=> ["[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},", 
    # "{a:9,b:10,c:11,d:12},", 
    # "{a:13,b:14,c:15,d:16}]"] 
doit(str, 21) 
    #=> ["[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},", 
    # "{a:9,b:10,c:11,d:12},", 
    # "{a:13,b:14,c:15,d:16}]"] 
doit(str, 22) # same for 23 <= min_size <= 37 
    #=> ["[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},", 
    # "{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}]"] 
doit(str, 38) # same for 39 <= min_size <= 58 
    #=> ["[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},", 
    # "{a:13,b:14,c:15,d:16}]"] 
doit(str, 59) # same for min_size > 59 
    #=> ["[{a:1,b:2,c:3,d:4},{a:5,b:6,c:7,d:8},{a:9,b:10,c:11,d:12},{a:13,b:14,c:15,d:16}]"] 
+0

正則表達式FTW!(雖然我不會將該方法命名爲「doit」)+1 –

+0

不錯。我沒有花太多時間嘗試一個「掃描」唯一的解決方案,但我沒有找到任何合適的正則表達式。 –

+0

這也是我第一次使用'。{32,}?'我不確定它會起作用,並且找不到任何關於它的文檔。 –