development

n 번째 문자마다 문자열을 분할 하시겠습니까?

big-blog 2020. 3. 4. 07:52
반응형

n 번째 문자마다 문자열을 분할 하시겠습니까?


파이썬 문자열을 n 번째 문자마다 나눌 수 있습니까?

예를 들어 다음을 포함하는 문자열이 있다고 가정합니다.

'1234567890'

어떻게 이렇게 보일 수 있습니까?

['12','34','56','78','90']

>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']

완료하기 위해 정규식 으로이 작업을 수행 할 수 있습니다.

>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']

주석에서 지적했듯이 다음을 수행 할 수 있습니다.

>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']

긴 청크에 대한 정규식을 단순화하기 위해 다음을 수행 할 수도 있습니다.

>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']

re.finditer문자열이 청크별로 청크를 생성하는 데 긴 경우 사용할 수 있습니다 .


파이썬에는 이미 내장 함수가 있습니다.

>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']

이것이 랩의 docstring이 말하는 것입니다 :

>>> help(wrap)
'''
Help on function wrap in module textwrap:

wrap(text, width=70, **kwargs)
    Wrap a single paragraph of text, returning a list of wrapped lines.

    Reformat the single paragraph in 'text' so it fits in lines of no
    more than 'width' columns, and return a list of wrapped lines.  By
    default, tabs in 'text' are expanded with string.expandtabs(), and
    all other whitespace characters (including newline) are converted to
    space.  See TextWrapper class for available keyword args to customize
    wrapping behaviour.
'''

요소를 n 길이 그룹으로 그룹화하는 또 다른 일반적인 방법은 다음과 같습니다.

>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']

이 방법은에 대한 문서에서 직접 제공됩니다 zip().


itertools 버전보다 짧고 읽기 쉽다고 생각합니다.

def split_by_n(seq, n):
    '''A generator to divide a sequence into chunks of n units.'''
    while seq:
        yield seq[:n]
        seq = seq[n:]

print(list(split_by_n('1234567890', 2)))

나는이 솔루션을 좋아한다 :

s = '1234567890'
o = []
while s:
    o.append(s[:2])
    s = s[2:]

PyPI의 더 많은 itertools 사용 :

>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']

다음에서 grouper()레시피를 사용할 수 있습니다 itertools.

파이썬 2.x :

from itertools import izip_longest    

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

파이썬 3.x :

from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

이 함수는 메모리 효율적이며 모든 이터 러블과 작동합니다.


이 시도:

s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])

산출:

['12', '34', '56', '78', '90']

다음 코드를 시도하십시오.

from itertools import islice

def split_every(n, iterable):
    i = iter(iterable)
    piece = list(islice(i, n))
    while piece:
        yield piece
        piece = list(islice(i, n))

s = '1234567890'
print list(split_every(2, list(s)))

>>> from functools import reduce
>>> from operator import add
>>> from itertools import izip
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x)]
['12', '34', '56', '78', '90']
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x, x)]
['123', '456', '789']

항상 그렇듯이 하나의 라이너를 좋아하는 사람들을 위해

n = 2  
line = "this is a line split into n characters"  
line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]

이 작업을 수행해야 할 때마다 사용하는이 코드가 있습니다.

def split_string(n, st):
    lst = [""]
    for i in str(st):
        l = len(lst) - 1
        if len(lst[l]) < n: 
            lst[l] += i
        else:
            lst += [i]
    return lst

print(split_string(3, "test_string."))

어디:

  • n 각 목록 항목의 길이입니다
  • st 분할 될 문자열입니다
  • lst 의 목록 버전입니다 st
  • i 현재 사용중인 문자입니다 st
  • l 마지막 목록 항목의 길이입니다

으스스한 하나 – 또 다른 답변을 발명하려고 시도했습니다.

def split(s, chunk_size):
    a = zip(*[s[i::chunk_size] for i in range(chunk_size)])
    return [''.join(t) for t in a]

print(split('1234567890', 1))
print(split('1234567890', 2))
print(split('1234567890', 3))

['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
['12', '34', '56', '78', '90']
['123', '456', '789']

def split(s, n):
  """
  Split string every nth character

  Parameters
  ----------
  s: string
  n: value of nth
  """
  new_list = []
  for i in range(0, len(s), n):
    new_list.append(s[i:i+n])
  return new_list

print(split('1234567890', 2))

more_itertools.sliced전에 언급 되었습니다 . more_itertools라이브러리의 추가 옵션은 다음과 같습니다 .

s = "1234567890"

["".join(c) for c in mit.grouper(2, s)]

["".join(c) for c in mit.chunked(s, 2)]

["".join(c) for c in mit.windowed(s, 2, step=2)]

["".join(c) for c in  mit.split_after(s, lambda x: int(x) % 2 == 0)]

후자의 각 옵션은 다음과 같은 출력을 생성합니다.

['12', '34', '56', '78', '90']

논의 옵션에 대한 문서 : grouper, chunked, windowed,split_after


나는이 질문이 오래되었다는 것을 알고 있지만 이것이 내가 알고있는 가장 짧은 방법입니다.

def split_every_n(S, n):
  return [S[i*n:(i+1)*n] for i in range(len(S) / n)]

그러나 이것은 문자열의 길이가 n의 배수라고 가정합니다. 그렇지 않으면 패딩해야합니다.


짧은 문자열을위한 간단한 재귀 솔루션 :

def split(s, n):
    if len(s) < n:
        return []
    else:
        return [s[:n]] + split(s[n:], n)

print(split('1234567890', 2))

또는 그런 형태로 :

def split(s, n):
    if len(s) < n:
        return []
    elif len(s) == n:
        return [s]
    else:
        return split(s[:n], n) + split(s[n:], n)

재귀 적 접근 방식에서 일반적인 분할 및 정복 패턴을보다 명확하게 보여줍니다 (실제로이 방법을 수행 할 필요는 없지만)


한 가지 가능성은 정규식을 사용하는 것입니다.

import re
re.findall("\w{3}", your_string)

좀 더 명확 할 수도 있습니다

##Define your string
mystring = '1234567890'

##Define your starting index
start = 0
##Define the end of your index for the first slice
end = 2

##Create an empty list
mylist =[]

##While the slice of characters without white space has something in it keep going
while len(mystring[start:end])>0:
    ##Add to the list
    mylist.append(mystring[start:end])
    ##Move the index up for the begining and ending of the slice
    start+=2
    end+=2

def splitstr(oldstr,n):
    start = 0
    end = n
    newlist =[]
    while len(oldstr[start:end])>0:
        newlist.append(oldstr[start:end])
        start+=n
        end+=n
    return newlist
print(splitstr('1234567890', 2))

청크의 길이가 같은 일반적인 경우에 대한 또 다른 해결책이 있습니다. 길이가 0이면 나머지 부분이 모두 반환됩니다.

data분할 될 시퀀스이고; fieldsize필드 길이 목록이있는 튜플입니다.

def fieldsplit(data=None, fieldsize=()):
    tmpl=[];
    for pp in fieldsize:
        if(pp>0):
            tmpl.append(line[:pp]);
            line=line[pp:];
        else:
            tmpl.append(line);
            break;
    return tuple(tmpl);

나는 이것을 사용하고있다 :

list(''.join(s) for s in zip(my_str[::2], my_str[1::2]))

또는 n대신 다른 번호를 사용할 수 있습니다 2.


이 질문은 Perl 6 .comb(n)방법을 생각 나게합니다 . 문자열을 n크기가 큰 청크 로 나눕니다 . (그것보다 더 많은 것이 있지만 세부 사항은 생략하겠습니다.)

Python3에서 람다 식으로 비슷한 함수를 구현하는 것은 쉽습니다.

comb = lambda s,n: [s[i:i+n] for i in range(0,len(s),n)]

그러면 다음과 같이 호출 할 수 있습니다.

comb('1234567', 2)   # returns ['12', '34', '56', '7']

comb()기능은 목록에서 작동하여 목록의 목록을 생성합니다.

comb(['cat', 'dog', 'bird'], 2)  # returns [['cat', 'dog'], ['bird']]

참고 URL : https://stackoverflow.com/questions/9475241/split-string-every-nth-character



반응형