How about zlib?
import zlib
a = "this string needs compressing"
a = zlib.compress(a.encode())
print(zlib.decompress(a).decode()) # outputs original contents of a
You can also use sys.getsizeof(obj) to see how much data an object takes up before and after compression.
How about zlib?
import zlib
a = "this string needs compressing"
a = zlib.compress(a.encode())
print(zlib.decompress(a).decode()) # outputs original contents of a
You can also use sys.getsizeof(obj) to see how much data an object takes up before and after compression.
import sys
import zlib
text=b"""This function is the primary interface to this module along with
decompress() function. This function returns byte object by compressing the data
given to it as parameter. The function has another parameter called level which
controls the extent of compression. It an integer between 0 to 9. Lowest value 0
stands for no compression and 9 stands for best compression. Higher the level of
compression, greater the length of compressed byte object."""
# Checking size of text
text_size=sys.getsizeof(text)
print("\nsize of original text",text_size)
# Compressing text
compressed = zlib.compress(text)
# Checking size of text after compression
csize=sys.getsizeof(compressed)
print("\nsize of compressed text",csize)
# Decompressing text
decompressed=zlib.decompress(compressed)
#Checking size of text after decompression
dsize=sys.getsizeof(decompressed)
print("\nsize of decompressed text",dsize)
print("\nDifference of size= ", text_size-csize)

compression - Create a compress function in Python? - Stack Overflow
String compression function in python code - Code Review Stack Exchange
String compression using dictionary [Python]
compress a string in python 3? - Stack Overflow
Here is a short python implementation of a compression function:
def compress(string):
res = ""
count = 1
#Add in first character
res += string[0]
#Iterate through loop, skipping last one
for i in range(len(string)-1):
if(string[i] == string[i+1]):
count+=1
else:
if(count > 1):
#Ignore if no repeats
res += str(count)
res += string[i+1]
count = 1
#print last one
if(count > 1):
res += str(count)
return res
Here are a few examples:
>>> compress("ddaaaff")
'd2a3f2'
>>> compress("daaaafffyy")
'da4f3y2'
>>> compress("mississippi")
'mis2is2ip2i'
Short version with generators:
from itertools import groupby
import re
def compress(string):
return re.sub(r'(?<![0-9])1', '', ''.join('%s%s' % (char, sum(1 for _ in group)) for char, group in groupby(string)))
(1) Grouping by chars with groupby(string)
(2) Counting length of group with sum(1 for _ in group) (because no len on group is possible)
(3) Joining into proper format
(4) Removing 1 chars for single items when there is a no digit before and after 1
Encapsulate your code into functions
Your code is neither reusable nor testable, wrap it into a function and call it from under an if __name__ == '__main__' guard. This will allow you to test it more easily. You will also be able to return values instead of printing them, this will make the code more reusable:
def compress(string):
temp={}
result=" "
for x in string:
if x in temp:
temp[x] = temp[x]+1
else:
temp[x] = 1
for key, value in temp.items():
result += str(key) + str(value)
return result
if __name__ == '__main__':
s = input("Enter the string:")
print(compress(s))
You can then jump into an interactive shell and type:
>>> from your_file_name import compress
>>> compress('aaabbccccddefg')
a3b2c4d2e1f1g1
>>> compress('b'*42)
b42
Use existing data structures
collections.Counter offers simplified ways of counting elements of an iterable:
from collections import Counter
def compress(string):
temp = Counter()
result = " "
for x in string:
temp[x] += 1
for key, value in temp.items():
result += str(key) + str(value)
return result
if __name__ == '__main__':
s = input("Enter the string:")
print(compress(s))
You can even simplify further as Counter can take any iterable in its constructor. You can also use str.join to simplify even further:
from collections import Counter
def compress(string):
counts = Counter(string)
return ''.join(letter+str(count) for letter, count in counts.items())
if __name__ == '__main__':
print(compress(input("Enter the string: ")))
Possible bug
To me, compressing a string mean having a mean to decompress it back. Using a dictionnary keyed by each letter as you do, you lost an important information: which letter is next to which one. Also 'aabaabaabaa' will be compressed to 'a8b3' which, to me, doesn't make sense and would be better as 'a2b1a2b1a2b1a2'. But I might be wrong. In this case, itertools.groupby is much more usefull as it will keep the ordering and avoid aggregating separate groups of letters:
import itertools
def compress(string):
return ''.join(
letter + str(len(list(group)))
for letter, group in itertools.groupby(string))
if __name__ == '__main__':
print(compress(input("Enter the string: ")))
In the itertools module there is the groupby function that groups together runs of the same values.
You can use it like this here:
from itertools import groupby
def compress(s):
out = []
for name, group in groupby(s):
length_of_run = len(list(group))
if length_of_run == 1:
out.append(name)
else:
out.append(f"{name}{length_of_run}")
return "".join(out)
This also uses the more modern f-strings instead of manually building the string with str calls and + and puts everything into a function that you can reuse.
It also has the advantage that it directly iterates over the input, instead of over its indices (have a look at Loop like a Native!). This makes it work also for a generator, which does not have a length:
from itertools import islice, cycle
compress(islice(cycle('a'), 10))
# 'a10'
I'm doing some practice interview questions and doing the problem below.
Problem
Given a string in the form 'AAAABBBBCCCCCDDEEEE' compress it to become 'A4B4C5D2E4'. For this problem, you can falsely "compress" strings of single or double letters. For instance, it is okay for 'AAB' to return 'A2B1' even though this technically takes more space.
The function should also be case sensitive, so that a string 'AAAaaa' returns 'A3a3'.
For my solution I decided to use the following approach.
Go through the string, For each character keep track of how many times they occur in a hashtable/dictionary.
def string_compression(string):
counter = {}
for s in string:
if s in counter:
counter[s] += 1
else:
counter[s] = 1
return "".join(['{0}{1}'.format(k, v) for k, v in counter.iteritems()])
The only problem I have with this solution is the order of Alphabets i.e AABBCC will return A2C2B2other than that, this seems to pass all the test cases.
I've seen the following used as a solution.
def compress(s):
"""
This solution compresses without checking. Known as the RunLength Compression algorithm.
"""
# Begin Run as empty string
r = ""
l = len(s)
# Check for length 0
if l == 0:
return ""
# Check for length 1
if l == 1:
return s + "1"
#Intialize Values
last = s[0]
cnt = 1
i = 1
while i < l:
# Check to see if it is the same letter
if s[i] == s[i - 1]:
# Add a count if same as previous
cnt += 1
else:
# Otherwise store the previous data
r = r + s[i - 1] + str(cnt)
cnt = 1
# Add to index count to terminate while loop
i += 1
# Put everything back into run
r = r + s[i - 1] + str(cnt)
return r
My question is, is there any issues with my approach? especially when it comes to performance? IIRC, looking up and setting items in a python Dictionary is O(1)
This is meant to enforce that you actually have a defined encoding.
zlib.compress("Hello, world".encode("utf-8"))
b'x\x9c\xf3H\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x00\x1b\xd4\x04i'
zlib.compress("Hello, world".encode("ascii"))
b'x\x9c\xf3H\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x00\x1b\xd4\x04i'
The same string could describe different byte sequences otherwise. But it is actually a byte sequence that will be encoded by zlib.
>>> zlib.compress("Hello, wørld".encode("utf-16"))
b'x\x9c\xfb\xff\xcf\x83!\x95!\x07\x08\xf3\x19t\x18\x14\x18\xca\x19~0\x14\x01y)\x0c\x00n\xa6\x06\xef'
>>> zlib.compress("Hello, wørld".encode("utf-8"))
b"x\x9c\xf3H\xcd\xc9\xc9\xd7Q(?\xbc\xa3('\x05\x00#\x7f\x05u"
In python 2.x strings are bytes string by default. In python 3.x they are unicode strings.
Compressing needs a byte string.