How do I split a string every nth character?
'1234567890' → ['12', '34', '56', '78', '90']
For the same question with a list, see How do I split a list into equally-sized chunks?.
How do I split a string every nth character?
'1234567890' → ['12', '34', '56', '78', '90']
For the same question with a list, see How do I split a list into equally-sized chunks?.
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
for i in range(0, len(string), n): print(string[i:i+n])
–
Luzon substrings = []
for i in range(0, len(line), n): substring = line[i:i+n] substrings.append(substring)
–
Predict \n
s and replaces them with spaces when I join them together –
Theda Just to be complete, you can do this with a regex:
>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
For odd number of chars you can do this:
>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']
You can also do the following, to simplify the regex for longer chunks:
>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']
And you can use re.finditer
if the string is long to generate chunk by chunk.
'.'*n
to make it more clear. No joining, no zipping, no loops, no list comprehension; just find the next two characters next to each other, which is exactly how a human brain thinks about it. If Monty Python were still alive, he'd love this method! –
Creep flags=re.S
. –
Satan There is already an inbuilt function in Python for this.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']
This is what the docstring for wrap
says:
>>> 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.
'''
wrap
may not return what is asked for if the string contains space. e.g. wrap('0 1 2 3 4 5', 2)
returns ['0', '1', '2', '3', '4', '5']
(the elements are stripped) –
Conductor wrap()
appears to be pretty slow (and much slower than say the regex solution): gitlab.com/snippets/1908857 –
Batrachian drop_whitespace=False
and break_on_hyphens=False
to prevent the issues stated by satomacoto and MrVocabulary. See the full documentation –
Unfrock ".".join(wrap(str(12345678)[::-1], 3))[::-1]
and you end up with 12.345.678
. –
Leuctra Another common way of grouping elements into n-length groups:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
This method comes straight from the docs for zip()
.
zip(*[iter(s)]*2)
tricky to understand, read How does zip(*[iter(s)]*n)
work in Python?. –
Canty >>> map(''.join, zip(*[iter('01234567')]*5))
-> ['01234']
–
Lissotrichous zip()
with itertools.zip_longest()
: map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
–
Bagel maps()
–
Legitimacy I think this is shorter and more readable than the itertools version:
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)))
Using more-itertools from PyPI:
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
I like this solution:
s = '1234567890'
o = []
while s:
o.append(s[:2])
s = s[2:]
You could use the grouper()
recipe from itertools
:
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)
from itertools import zip_longest
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
"Collect data into non-overlapping fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
args = [iter(iterable)] * n
if incomplete == 'fill':
return zip_longest(*args, fillvalue=fillvalue)
if incomplete == 'strict':
return zip(*args, strict=True)
if incomplete == 'ignore':
return zip(*args)
else:
raise ValueError('Expected fill, strict, or ignore')
These functions are memory-efficient and work with any iterables.
This can be achieved by a simple for loop.
a = '1234567890a'
result = []
for i in range(0, len(a), 2):
result.append(a[i : i + 2])
print(result)
The output looks like ['12', '34', '56', '78', '90', 'a']
I was stuck in the same scenario.
This worked for me:
x = "1234567890"
n = 2
my_list = []
for i in range(0, len(x), n):
my_list.append(x[i:i+n])
print(my_list)
Output:
['12', '34', '56', '78', '90']
Try this:
s = '1234567890'
print([s[idx:idx+2] for idx in range(len(s)) if idx % 2 == 0])
Output:
['12', '34', '56', '78', '90']
for i in range(len(s))
; why iterate over every value only to throw away half of them? just skip the values you don't need: for i in range(0, len(s), 2)
(and skip the if
part) –
Margaretmargareta Try the following code:
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)))
yield ''.join(piece)
to make it work as expected: eval.in/813878 –
Bagel As always, for those who love one liners:
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])]
print(line)
I get this is a line split into n characters
as the output. Might you be better putting: line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
? Fix this and it's a good answer :). –
Robbins ,blah
and why it's necessary? I notice I can replace blah
with any alpha character/s, but not numbers, and can't remove the blah
or/and the comma. My editor suggests adding whitespace after ,
:s –
Xantha enumerate
returns two iterables, so you need two places to put them. But you don't actually need the second iterable for anything in this case. –
Submissive blah
I prefer to use an underscore or double underscore, see: #5893663 –
Parados >>> 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']
A simple recursive solution for short string:
def split(s, n):
if len(s) < n:
return []
else:
return [s[:n]] + split(s[n:], n)
print(split('1234567890', 2))
Or in such a form:
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)
, which illustrates the typical divide and conquer pattern in recursive approach more explicitly (though practically it is not necessary to do it this way)
more_itertools.sliced
has been mentioned before. Here are four more options from the more_itertools
library:
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)]
Each of the latter options produce the following output:
['12', '34', '56', '78', '90']
Documentation for discussed options: grouper
, chunked
, windowed
, split_after
A solution with groupby
:
from itertools import groupby, chain, repeat, cycle
text = "wwworldggggreattecchemggpwwwzaz"
n = 3
c = cycle(chain(repeat(0, n), repeat(1, n)))
res = ["".join(g) for _, g in groupby(text, lambda x: next(c))]
print(res)
Output:
['www', 'orl', 'dgg', 'ggr', 'eat', 'tec', 'che', 'mgg', 'pww', 'wza', 'z']
Another solution using groupby
and index//n
as the key to group the letters:
from itertools import groupby
text = "abcdefghij"
n = 3
result = []
for idx, chunk in groupby(text, key=lambda x: x.index//n):
result.append("".join(chunk))
# result = ['abc', 'def', 'ghi', 'j']
These answers are all nice and working and all, but the syntax is so cryptic... Why not write a simple function?
def SplitEvery(string, length):
if len(string) <= length: return [string]
sections = len(string) / length
lines = []
start = 0;
for i in range(sections):
line = string[start:start+length]
lines.append(line)
start += length
return lines
And call it simply:
text = '1234567890'
lines = SplitEvery(text, 2)
print(lines)
# output: ['12', '34', '56', '78', '90']
A full write-up with updated solutions can be found here on Github.
NOTE: Solutions are written for Python3.10+
Using List Comprehension and Slicing: This is a simple and straightforward approach where we can use Python’s slicing feature to split the string into chunks of n characters. We can use list comprehension to iterate over the string with a step size of n and slice the string from the current index to the current index plus n.
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters.
This function uses list comprehension and slicing to split the string into groups.
It includes error handling to check if `n` is a positive integer.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings, where each string is a group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use list comprehension and slicing to split the string into groups of `n` characters.
return [s[i:i + n] for i in range(0, len(s), n)]
Using the re (regex) Module: Python’s re module provides a function called findall(), which can be used to find all occurrences of a pattern in a string. We can use this function with a regular expression that matches any n characters to split the string into chunks of n characters.
import re
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters.
This function uses the `re.findall()` function from the `re` (regex) module to solve the problem.
It includes error handling to check if `n` is a positive integer.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings, where each string is a group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use `re.findall()` to split the string into groups of `n` characters.
return re.findall(f'.{{1,{n}}}', s)
Using the textwrap Module: The textwrap module in Python provides a function called wrap(), which can be used to split a string into a list of output lines of specified width. We can use this function to split the string into chunks of n characters.
import textwrap
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters.
This function uses the `textwrap.wrap()` function from the `textwrap` module to solve the problem.
It includes error handling to check if `n` is a positive integer.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings, where each string is a group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use `textwrap.wrap()` to split the string into groups of `n` characters.
return textwrap.wrap(s, n)
Using a Loop and String Concatenation: We can also solve this problem by manually looping over the string and concatenating n characters at a time to a new string. Once we have n characters, we can add the new string to a list and reset the new string to an empty string.
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters.
This function uses a loop and string concatenation to solve the problem.
It includes error handling to check if `n` is a positive integer.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings, where each string is a group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Initialize an empty list to store the groups.
result = []
# Initialize an empty string to store the current group.
group = ''
# Iterate over each character in the string.
for c in s:
group += c # Add the current character to the current group.
# If the current group has `n` characters, add it to the result and reset the group.
if len(group) == n:
result.append(group)
group = ''
# If there are any remaining characters in the group, add it to the result.
if group:
result.append(group)
return result
Using Generator Function: We can create a generator function that takes a string and a number n as input and yields chunks of n characters from the string. This approach is memory efficient as it doesn’t require storing all chunks in memory at once.
from typing import Generator
def split_string_into_groups(string: str, n: int) -> Generator[str, None, None]:
"""
Generator function to split a string into groups of `n` consecutive characters.
Args:
string (str): The input string to be split.
n (int): The size of the groups.
Yields:
str: The next group of `n` characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> list(split_string_into_groups("HelloWorld", 3))
['Hel', 'loW', 'orl', 'd']
>>> list(split_string_into_groups("Python", 2))
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Iterate over the string with a step size of `n`.
for i in range(0, len(string), n):
# Yield the next group of `n` characters.
yield string[i:i + n]
Using itertools: The itertools module in Python provides a function called islice(), which can be used to slice an iterable. We can use this function to split the string into chunks of n characters.
from itertools import islice
from typing import Iterator
def split_string_into_groups(s: str, n: int) -> Iterator[str]:
"""
Splits a string into groups of `n` consecutive characters using itertools.islice().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
Iterator[str]: An iterator that yields each group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> list(split_string_into_groups("HelloWorld", 3))
['Hel', 'loW', 'orl', 'd']
>>> list(split_string_into_groups("Python", 2))
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Create an iterator from the string.
it = iter(s)
# Use itertools.islice() to yield groups of `n` characters from the iterator.
while True:
group = ''.join(islice(it, n))
if not group:
break
yield group
Using numpy: We can also use the numpy library to solve this problem. We can convert the string to a numpy array and then use the reshape() function to split the array into chunks of n characters.
import numpy as np
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using numpy.reshape().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Convert the string to a list of characters
chars = list(s)
# Add extra empty strings only if the length of `s` is not a multiple of `n`
if len(s) % n != 0:
chars += [''] * (n - len(s) % n)
# Reshape the array into a 2D array with the number of groups as the number of rows and n as the number of columns
arr = np.array(chars).reshape(-1, n)
# Convert each row of the 2D array back to a string and add it to the result list
result = [''.join(row).rstrip() for row in arr]
return result
Using pandas: The pandas library in Python provides a function called groupby(), which can be used to split an array into bins. We can use this function to split the string into chunks of n characters.
import pandas as pd
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a given string into groups of `n` consecutive characters.
This function uses the pandas library to convert the string into a pandas Series,
then uses the groupby method to group the characters into groups of `n` characters.
The groups are then converted back to a list of strings.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings, where each string is a group of `n` consecutive characters from the input string.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Convert the string to a pandas Series
s = pd.Series(list(s))
# Use pandas groupby to group the characters
# The index of each character is divided by `n` using integer division,
# which groups the characters into groups of `n` characters.
groups = s.groupby(s.index // n).agg(''.join)
# Convert the result back to a list and return it
return groups.tolist()
Using more_itertools: The more_itertools library provides a function called chunked(), which can be used to split an iterable into chunks of a specified size. We can use this function to split the string into chunks of n characters.
import more_itertools
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using more_itertools.chunked().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use more_itertools.chunked() to split the string into chunks of `n` characters.
chunks = more_itertools.chunked(s, n)
# Convert each chunk to a string and add it to the result list.
result = [''.join(chunk) for chunk in chunks]
return result
Using toolz: The toolz library provides a function called partition_all(), which can be used to split an iterable into chunks of a specified size. We can use this function to split the string into chunks of n characters.
import toolz
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using toolz.partition_all().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use toolz.partition_all() to split the string into chunks of `n` characters.
chunks = toolz.partition_all(n, s)
# Convert each chunk to a string and add it to the result list.
result = [''.join(chunk) for chunk in chunks]
return result
Using cytoolz: The cytoolz library provides a function called partition_all(), which can be used to split an iterable into chunks of a specified size. We can use this function to split the string into chunks of n characters.
from cytoolz import partition_all
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using cytoolz.partition_all().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use cytoolz.partition_all() to split the string into chunks of `n` characters.
chunks = partition_all(n, s)
# Convert each chunk to a string and add it to the result list.
result = [''.join(chunk) for chunk in chunks]
return result
Using itertools: The itertools library provides a function called zip_longest, which can be used to split an iterable into chunks of a specified size. We can use this function to split the string into chunks of n characters.
from itertools import zip_longest
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using itertools.zip_longest().
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
List[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use itertools.zip_longest() to split the string into chunks of `n` characters.
args = [iter(s)] * n
chunks = zip_longest(*args, fillvalue='')
# Convert each chunk to a string and add it to the result list.
result = [''.join(chunk) for chunk in chunks]
return result
Using list + map + join + zip: We can also solve this problem using the list function, the map function, the join method, and the zip function. We can use the map function to iterate over the string with a step size of n and slice the string from the current index to the current index plus n. We can then use the zip function to combine the chunks into a list of tuples, and the join method to join the tuples into a list of strings.
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using list, map, join, and zip.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Use list, map, join, and zip to split the string into chunks of `n` characters.
result = [''.join(chunk) for chunk in zip(*[iter(s)] * n)]
# If the string length is not a multiple of `n`, add the remaining characters to the result.
remainder = len(s) % n
if remainder != 0:
result.append(s[-remainder:])
return result
Using Recursion with Slicing: We can also solve this problem using recursion and slicing. We can define a recursive function that takes a string and a number n as input and returns a list of chunks of n characters. The function can slice the string into chunks of n characters and call itself recursively with the remaining string until the string is empty.
def split_string_into_groups(s: str, n: int) -> list[str]:
"""
Splits a string into groups of `n` consecutive characters using recursion with slicing.
Args:
s (str): The input string to be split.
n (int): The size of the groups.
Returns:
list[str]: A list of strings where each string is a group of `n` consecutive characters.
Raises:
ValueError: If `n` is not a positive integer.
Examples:
>>> split_string_into_groups("HelloWorld", 3)
['Hel', 'loW', 'orl', 'd']
>>> split_string_into_groups("Python", 2)
['Py', 'th', 'on']
"""
# Check if `n` is a positive integer.
if n <= 0:
raise ValueError("The group size must be a positive integer")
# Base case: if the length of the string is less than or equal to `n`, return a list containing `s`.
if len(s) <= n:
return [s]
# Recursive case: split the string into two parts and recursively call `split_string_into_groups` on the rest of the string.
return [s[:n]] + split_string_into_groups(s[n:], n)
© 2022 - 2024 — McMap. All rights reserved.