文字列の均等分割
この問題は、除算だけでははく算術演算とか、文字列の長さをstrlenの類いで測るとかをしなくても、多分書けるのではないかと思います。
Posted feedbacks - Python
昼休みの時間にさくっと書いてみる。 割り算とほぼ同等なことをやってるあたりがダメダメだなぁ。 以下出力結果 dev4 ゆめよりもはかなき世のなかを なげきわびつゝあかしくらすほ どに四月十よひにもなりぬれ ば木のしたくらがりもてゆく dev5 ゆめよりもはかなき世の なかをなげきわびつゝあ かしくらすほどに四月十 よひにもなりぬれば木の したくらがりもてゆく dev6 ゆめよりもはかなき 世のなかをなげきわ びつゝあかしくらす ほどに四月十よひに もなりぬれば木のし たくらがりもてゆく
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #-*- coding: utf-8 -*-
def dev(s,num):
tempCount = [0]*num
outStr = [""]*num
i = 0
for j in xrange(len(s)):
tempCount[i] += 1
i = i+1
if i == num:
i=0
for x in xrange(num):
outStr[x] = s[:tempCount[x]]
s = s[tempCount[x]:]
return outStr
#配列をそのままプリントするとユニコードがうまく表示されないので
def printArray(array):
for x in array:
print x
sample = u"ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく"
print "dev4"
printArray(dev(sample,4))
print "dev5"
printArray(dev(sample,5))
print "dev6"
printArray(dev(sample,6))
|
正規表現を使いました。
countは0以上の無限リストを作成する命令で、0以上の各整数iについて「『i文字またはi+1文字』のブロックがn個ある」という正規表現を作ってマッチを試みます。マッチすればグループ分けをreturn。greedyなので前半のグループが長い方、後半のグループが短い方になります。
1 2 3 4 5 6 7 8 | def divid(n, s):
import re
from itertools import count
for i in count():
pat = "^%s$" % "(.?.{%d})" % i * n
m = re.match(pat, s)
if m:
return m.groups()
|
文字数数えるのが面倒だったので、スライスでn個飛ばしの文字列を作って、それの文字数を使いました。 オフセット数えるのも、面倒なので再帰任せです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # encoding: utf-8
sample = u"ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく"
def divid(str, n, target_list=[]):
def get_splitted_str(str, n):
return str[:len(str[::n])]
if str:
s = get_splitted_str(str, n)
return divid(str[len(s):], n-1, target_list+[s])
else: return target_list
for i in range(4,7):
print "divid", i
l = divid(sample, i)
for line in l:
print line
print ""
|
なるほど。その発想を使ってみました。 cycleは与えられたリストを巡回し続ける無限リストで、zipは短い方に会わせて切り詰めます。
これでも算術演算やstrlenは必要ないですね…正規表現を使うよりは黒魔術っぽさがなくていいかも。
>>> cycle(range(3)) <itertools.cycle object at 0x0270AAA8> >>> zip(_, "hoge") [(0, 'h'), (1, 'o'), (2, 'g'), (0, 'e')]
1 2 3 4 5 | def divid(n, s):
from itertools import cycle
xs = zip(cycle(range(n)), s)
return ["".join(c for i, c in xs if i == j)
for j in range(n)]
|
算術演算も文字列長取得関数も使っていません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #-*- coding: utf-8 -*-
def divid(n, s):
s = unicode(s, 'utf-8')
sl = list(s)
l = []
while s:
l.append(list(s[:n]))
s = s[n:]
print '\ndivid %d sample =>' % n
while l[0]:
print ' "%s"' % ''.join([a.pop(0) and sl.pop(0) for a in l if a])
sample = 'ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく'
print '"sample = %s"' % sample
divid(4, sample)
divid(5, sample)
divid(6, sample)
|




nobsun
#4090()
Rating-1/3=-0.33
1 reply [ reply ]