String compression function in python code [on hold]












3














I need to create a function called compress that compresses a string by replacing any repeated letters with a letter and number. Can someone suggest a better way to do this?



s=input("Enter the string:")
temp={}
result=" "
for x in s:
if x in temp:
temp[x]=temp[x]+1
else:
temp[x]=1
for key,value in temp.items():
result+=str(key)+str(value)
print(result)









share|improve this question









New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











put on hold as off-topic by Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld yesterday


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld

If this question can be reworded to fit the rules in the help center, please edit the question.









  • 4




    Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
    – Graipher
    2 days ago








  • 2




    In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
    – Sᴀᴍ Onᴇᴌᴀ
    yesterday
















3














I need to create a function called compress that compresses a string by replacing any repeated letters with a letter and number. Can someone suggest a better way to do this?



s=input("Enter the string:")
temp={}
result=" "
for x in s:
if x in temp:
temp[x]=temp[x]+1
else:
temp[x]=1
for key,value in temp.items():
result+=str(key)+str(value)
print(result)









share|improve this question









New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











put on hold as off-topic by Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld yesterday


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld

If this question can be reworded to fit the rules in the help center, please edit the question.









  • 4




    Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
    – Graipher
    2 days ago








  • 2




    In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
    – Sᴀᴍ Onᴇᴌᴀ
    yesterday














3












3








3







I need to create a function called compress that compresses a string by replacing any repeated letters with a letter and number. Can someone suggest a better way to do this?



s=input("Enter the string:")
temp={}
result=" "
for x in s:
if x in temp:
temp[x]=temp[x]+1
else:
temp[x]=1
for key,value in temp.items():
result+=str(key)+str(value)
print(result)









share|improve this question









New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I need to create a function called compress that compresses a string by replacing any repeated letters with a letter and number. Can someone suggest a better way to do this?



s=input("Enter the string:")
temp={}
result=" "
for x in s:
if x in temp:
temp[x]=temp[x]+1
else:
temp[x]=1
for key,value in temp.items():
result+=str(key)+str(value)
print(result)






python python-3.x python-2.x






share|improve this question









New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 2 days ago









Mathias Ettinger

23.8k33182




23.8k33182






New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 2 days ago









instaggyinstaggy

244




244




New contributor




instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






instaggy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




put on hold as off-topic by Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld yesterday


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld

If this question can be reworded to fit the rules in the help center, please edit the question.




put on hold as off-topic by Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld yesterday


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Graipher, Donald.McLean, Sᴀᴍ Onᴇᴌᴀ, IEatBagels, AJNeufeld

If this question can be reworded to fit the rules in the help center, please edit the question.








  • 4




    Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
    – Graipher
    2 days ago








  • 2




    In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
    – Sᴀᴍ Onᴇᴌᴀ
    yesterday














  • 4




    Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
    – Graipher
    2 days ago








  • 2




    In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
    – Sᴀᴍ Onᴇᴌᴀ
    yesterday








4




4




Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
– Graipher
2 days ago






Your code does not seem to actually solve the problem you stated. The order of letters is not preserved and if a letter only occures once you add a 1 instead of just outputting it ("aba" -> "a2b1" instead of "aba" -> "aba").
– Graipher
2 days ago






2




2




In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
– Sᴀᴍ Onᴇᴌᴀ
yesterday




In addition to the problem Graipher reported, there is also unexepected indentation on the last line...
– Sᴀᴍ Onᴇᴌᴀ
yesterday










4 Answers
4






active

oldest

votes


















-5














You can try to debug yourself and come up with many solutions.A way out of many I can tell you is below:



res = ""
count = 0
while (len(x) > 0):
count = 1
res= ""
for j in range(1, len(x)):
if x[0]==x[j]:
count= count + 1
else:
res = res + x[j]
print(x[0], count, end=" ")
x=res





share|improve this answer








New contributor




Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed.










  • 9




    You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
    – Mathias Ettinger
    2 days ago



















8














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: ")))





share|improve this answer























  • And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
    – Graipher
    2 days ago






  • 1




    @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
    – Mathias Ettinger
    2 days ago






  • 2




    @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
    – Mathias Ettinger
    2 days ago






  • 1




    The more I look at it, the code of the OP does not solve the stated problem at all...
    – Graipher
    2 days ago










  • Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
    – Graipher
    2 days ago



















2














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'





share|improve this answer































    -2














    This could be one of the way to do it:



    count = 1
    for i in range(1, len(input) + 1):
    if i == len(input):
    print(input[i - 1] + str(count), end="")
    break
    else:
    if input[i - 1] == input[i]:
    count += 1
    else:
    print(input[i - 1] + str(count), end="")
    count = 1





    share|improve this answer








    New contributor




    pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















    • Thanks, something wrong with my code?
      – instaggy
      2 days ago










    • Not really, just suggested you a better way to perform the same per your question.
      – pycoder223
      2 days ago










    • Many thanks, this works fine as well.
      – instaggy
      2 days ago






    • 5




      You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
      – Mathias Ettinger
      2 days ago


















    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    -5














    You can try to debug yourself and come up with many solutions.A way out of many I can tell you is below:



    res = ""
    count = 0
    while (len(x) > 0):
    count = 1
    res= ""
    for j in range(1, len(x)):
    if x[0]==x[j]:
    count= count + 1
    else:
    res = res + x[j]
    print(x[0], count, end=" ")
    x=res





    share|improve this answer








    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.








    We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed.










    • 9




      You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
      – Mathias Ettinger
      2 days ago
















    -5














    You can try to debug yourself and come up with many solutions.A way out of many I can tell you is below:



    res = ""
    count = 0
    while (len(x) > 0):
    count = 1
    res= ""
    for j in range(1, len(x)):
    if x[0]==x[j]:
    count= count + 1
    else:
    res = res + x[j]
    print(x[0], count, end=" ")
    x=res





    share|improve this answer








    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.








    We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed.










    • 9




      You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
      – Mathias Ettinger
      2 days ago














    -5












    -5








    -5






    You can try to debug yourself and come up with many solutions.A way out of many I can tell you is below:



    res = ""
    count = 0
    while (len(x) > 0):
    count = 1
    res= ""
    for j in range(1, len(x)):
    if x[0]==x[j]:
    count= count + 1
    else:
    res = res + x[j]
    print(x[0], count, end=" ")
    x=res





    share|improve this answer








    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    You can try to debug yourself and come up with many solutions.A way out of many I can tell you is below:



    res = ""
    count = 0
    while (len(x) > 0):
    count = 1
    res= ""
    for j in range(1, len(x)):
    if x[0]==x[j]:
    count= count + 1
    else:
    res = res + x[j]
    print(x[0], count, end=" ")
    x=res






    share|improve this answer








    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    share|improve this answer



    share|improve this answer






    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    answered 2 days ago









    Alex56Alex56

    113




    113




    New contributor




    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





    New contributor





    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    Alex56 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.



    We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed.




    We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed.









    • 9




      You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
      – Mathias Ettinger
      2 days ago














    • 9




      You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
      – Mathias Ettinger
      2 days ago








    9




    9




    You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
    – Mathias Ettinger
    2 days ago




    You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
    – Mathias Ettinger
    2 days ago













    8














    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: ")))





    share|improve this answer























    • And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
      – Graipher
      2 days ago






    • 1




      @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
      – Mathias Ettinger
      2 days ago






    • 2




      @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
      – Mathias Ettinger
      2 days ago






    • 1




      The more I look at it, the code of the OP does not solve the stated problem at all...
      – Graipher
      2 days ago










    • Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
      – Graipher
      2 days ago
















    8














    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: ")))





    share|improve this answer























    • And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
      – Graipher
      2 days ago






    • 1




      @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
      – Mathias Ettinger
      2 days ago






    • 2




      @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
      – Mathias Ettinger
      2 days ago






    • 1




      The more I look at it, the code of the OP does not solve the stated problem at all...
      – Graipher
      2 days ago










    • Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
      – Graipher
      2 days ago














    8












    8








    8






    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: ")))





    share|improve this answer














    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: ")))






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered 2 days ago









    Mathias EttingerMathias Ettinger

    23.8k33182




    23.8k33182












    • And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
      – Graipher
      2 days ago






    • 1




      @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
      – Mathias Ettinger
      2 days ago






    • 2




      @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
      – Mathias Ettinger
      2 days ago






    • 1




      The more I look at it, the code of the OP does not solve the stated problem at all...
      – Graipher
      2 days ago










    • Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
      – Graipher
      2 days ago


















    • And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
      – Graipher
      2 days ago






    • 1




      @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
      – Mathias Ettinger
      2 days ago






    • 2




      @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
      – Mathias Ettinger
      2 days ago






    • 1




      The more I look at it, the code of the OP does not solve the stated problem at all...
      – Graipher
      2 days ago










    • Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
      – Graipher
      2 days ago
















    And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
    – Graipher
    2 days ago




    And then encoding 'f' as 'f1' is the opposite of compressing. But if you find a nice way to write it as a comprehension that would be nice, I could not think of any.
    – Graipher
    2 days ago




    1




    1




    @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
    – Mathias Ettinger
    2 days ago




    @Graipher For 'f' -> 'f1' I chose to keep the original behaviour
    – Mathias Ettinger
    2 days ago




    2




    2




    @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
    – Mathias Ettinger
    2 days ago




    @Graipher But something like letter + str(length := len(list(group))) if length > 1 else '' could work in upcomming Python 3.8
    – Mathias Ettinger
    2 days ago




    1




    1




    The more I look at it, the code of the OP does not solve the stated problem at all...
    – Graipher
    2 days ago




    The more I look at it, the code of the OP does not solve the stated problem at all...
    – Graipher
    2 days ago












    Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
    – Graipher
    2 days ago




    Yeah, I was thinking along those lines as well. But I only have 3.6 installed :)
    – Graipher
    2 days ago











    2














    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'





    share|improve this answer




























      2














      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'





      share|improve this answer


























        2












        2








        2






        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'





        share|improve this answer














        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'






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 days ago

























        answered 2 days ago









        GraipherGraipher

        23.7k53585




        23.7k53585























            -2














            This could be one of the way to do it:



            count = 1
            for i in range(1, len(input) + 1):
            if i == len(input):
            print(input[i - 1] + str(count), end="")
            break
            else:
            if input[i - 1] == input[i]:
            count += 1
            else:
            print(input[i - 1] + str(count), end="")
            count = 1





            share|improve this answer








            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.


















            • Thanks, something wrong with my code?
              – instaggy
              2 days ago










            • Not really, just suggested you a better way to perform the same per your question.
              – pycoder223
              2 days ago










            • Many thanks, this works fine as well.
              – instaggy
              2 days ago






            • 5




              You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
              – Mathias Ettinger
              2 days ago
















            -2














            This could be one of the way to do it:



            count = 1
            for i in range(1, len(input) + 1):
            if i == len(input):
            print(input[i - 1] + str(count), end="")
            break
            else:
            if input[i - 1] == input[i]:
            count += 1
            else:
            print(input[i - 1] + str(count), end="")
            count = 1





            share|improve this answer








            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.


















            • Thanks, something wrong with my code?
              – instaggy
              2 days ago










            • Not really, just suggested you a better way to perform the same per your question.
              – pycoder223
              2 days ago










            • Many thanks, this works fine as well.
              – instaggy
              2 days ago






            • 5




              You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
              – Mathias Ettinger
              2 days ago














            -2












            -2








            -2






            This could be one of the way to do it:



            count = 1
            for i in range(1, len(input) + 1):
            if i == len(input):
            print(input[i - 1] + str(count), end="")
            break
            else:
            if input[i - 1] == input[i]:
            count += 1
            else:
            print(input[i - 1] + str(count), end="")
            count = 1





            share|improve this answer








            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            This could be one of the way to do it:



            count = 1
            for i in range(1, len(input) + 1):
            if i == len(input):
            print(input[i - 1] + str(count), end="")
            break
            else:
            if input[i - 1] == input[i]:
            count += 1
            else:
            print(input[i - 1] + str(count), end="")
            count = 1






            share|improve this answer








            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            share|improve this answer



            share|improve this answer






            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            answered 2 days ago









            pycoder223pycoder223

            14




            14




            New contributor




            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.





            New contributor





            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.






            pycoder223 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.












            • Thanks, something wrong with my code?
              – instaggy
              2 days ago










            • Not really, just suggested you a better way to perform the same per your question.
              – pycoder223
              2 days ago










            • Many thanks, this works fine as well.
              – instaggy
              2 days ago






            • 5




              You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
              – Mathias Ettinger
              2 days ago


















            • Thanks, something wrong with my code?
              – instaggy
              2 days ago










            • Not really, just suggested you a better way to perform the same per your question.
              – pycoder223
              2 days ago










            • Many thanks, this works fine as well.
              – instaggy
              2 days ago






            • 5




              You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
              – Mathias Ettinger
              2 days ago
















            Thanks, something wrong with my code?
            – instaggy
            2 days ago




            Thanks, something wrong with my code?
            – instaggy
            2 days ago












            Not really, just suggested you a better way to perform the same per your question.
            – pycoder223
            2 days ago




            Not really, just suggested you a better way to perform the same per your question.
            – pycoder223
            2 days ago












            Many thanks, this works fine as well.
            – instaggy
            2 days ago




            Many thanks, this works fine as well.
            – instaggy
            2 days ago




            5




            5




            You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
            – Mathias Ettinger
            2 days ago




            You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process.
            – Mathias Ettinger
            2 days ago



            Popular posts from this blog

            An IMO inspired problem

            Management

            Has there ever been an instance of an active nuclear power plant within or near a war zone?