2012-10-13 10 views
16

Szukam sposobu na skompresowanie łańcucha ASCII, jakiejkolwiek pomocy?Python - Compress Ascii String

Potrzebuję też go rozpakować. Próbowałem zlib, ale bez żadnej pomocy.

Co mogę zrobić, aby skompresować napis na mniejszą długość?

Kod:

def compress(request): 
    if request.POST: 
     data = request.POST.get('input') 
     if is_ascii(data): 
      result = zlib.compress(data) 
      return render_to_response('index.html', {'result': result, 'input':data}, context_instance = RequestContext(request)) 
     else: 
      result = "Error, the string is not ascii-based" 
      return render_to_response('index.html', {'result':result}, context_instance = RequestContext(request)) 
    else: 
     return render_to_response('index.html', {}, context_instance = RequestContext(request)) 
+0

Patrz http://en.literateprograms.org/Huffman_coding_(Python) – GodMan

+0

Dlaczego nie zlib pomóc? – Sergey

+0

Próbowałem zwrócić ciąg znaków, ale nie działało. – moenad

Odpowiedz

23

użyciu kompresji nie zawsze zmniejszyć długość łańcucha!

Należy rozważyć następujący kod;

import zlib 
import bz2 

def comptest(s): 
    print 'original length:', len(s) 
    print 'zlib compressed length:', len(zlib.compress(s)) 
    print 'bz2 compressed length:', len(bz2.compress(s)) 

Spróbujmy tego na pustym łańcuchu;

In [15]: comptest('') 
original length: 0 
zlib compressed length: 8 
bz2 compressed length: 14 

Więc zlib produkuje dodatkowe 8 znaków i bz2 14. Metody kompresji zazwyczaj umieścić nagłówek „” przed skompresowanych danych na użytek programu dekompresji. Ten nagłówek zwiększa długość wyjścia.

Przetestujmy jedno słowo;

In [16]: comptest('test') 
original length: 4 
zlib compressed length: 12 
bz2 compressed length: 40 

Nawet w przypadku odjęcia długości nagłówka kompresja nie spowodowała skrócenia słowa. Dzieje się tak dlatego, że w tym przypadku niewiele jest do kompresji. Większość znaków w łańcuchu występuje tylko raz. Teraz na krótkie zdanie;

In [17]: comptest('This is a compression test of a short sentence.') 
original length: 47 
zlib compressed length: 52 
bz2 compressed length: 73 

Ponownie wyjście kompresji większa niż tekstu wejściowego. Z powodu ograniczonej długości tekstu, jest w nim niewiele powtórzeń, więc nie będzie się dobrze kompresował.

Potrzebujesz dość długiego bloku tekstu, aby kompresja rzeczywiście zadziałała;

In [22]: rings = ''' 
    ....:  Three Rings for the Elven-kings under the sky, 
    ....:  Seven for the Dwarf-lords in their halls of stone, 
    ....:  Nine for Mortal Men doomed to die, 
    ....:  One for the Dark Lord on his dark throne 
    ....:  In the Land of Mordor where the Shadows lie. 
    ....:  One Ring to rule them all, One Ring to find them, 
    ....:  One Ring to bring them all and in the darkness bind them 
    ....:  In the Land of Mordor where the Shadows lie.''' 

In [23]: comptest(rings)      
original length: 410 
zlib compressed length: 205 
bz2 compressed length: 248 
+0

Należy zauważyć, że dla Pythona 3, dane wejściowe do 'zlib.compress' i' bz2.compress' muszą być w bajtach, więc musisz '.encode()' najpierw napisać – mschrimpf

6

Nie trzeba nawet być Ci dane ASCII, można karmić zlib z niczego

>>> import zlib 
>>> a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' # + any binary data you want 
>>> print zlib.compress(a) 
x�KL$ 
� 
>>> 

Co prawdopodobnie chcesz tutaj - skompresowane dane jako ciąg ASCII ? Czy jestem tutaj?
Jeśli tak - powinieneś wiedzieć, że masz bardzo mały alfabet kodujący skompresowane dane =>, więc będziesz miał więcej używanych symboli.

Na przykład kod danych binarnych w base64 (dostaniesz ciąg ASCII), ale można użyć ~ 30% więcej przestrzeni dla tej

Powiązane problemy