Sorted returns white space inside the Array

Asked

Viewed 154 times

1

I want the program to receive 2 numbers and show them in ascending order:

a = input()
x = a
print(sorted(x))

But with that when I write 3 2, he shows [" ", "2", "3"]. How do I eliminate space?

  • Why don’t you wear it like this: print(sorted([int(x) for x in input() if x.isdigit()])) ?

  • @cat The problem is if you have numbers with more than one digit (like 12 3, for example): https://ideone.com/ihagh3

  • 1

    @hkotsubo mobile is bad to type, I miss the split() :)

2 answers

5

First understand that input returns a string. So if you type 3 2, that is a string (a text). Although there are two numbers in this string, they are not interpreted as actual numbers.

And when you pass a string to sorted, the result is a list in which each element is a string character:

print(sorted('bdca')) # ['a', 'b', 'c', 'd']

In the above example, the result is the list ['a', 'b', 'c', 'd']. If the string has spaces, they are also considered in the sort. Another detail is that if you have numbers with more than one digit, each digit is also considered a character:

print(sorted('12 3')) # [' ', '1', '2', '3']

In the above case, the output is [' ', '1', '2', '3'] - the string characters ordered in the "alphabetical" order (actually, according to the order defined by your Unicode Code Points).


So to get the numbers, first you must separate them by space. For this you can use split, which will create a list of space-separated elements. Thus, the string '3 2' turns the list ['3', '2'].

Then we can use int to convert each element of this list to number, and use sorted to sort the numbers in ascending order.

Finally, you can also use isdigit to make sure that the element is actually a number:

a = '12 3 2 5343'
x = sorted(int(n) for n in a.split(' ') if n.isdigit())
print(x)

This prints:

[2, 3, 12, 5343]

I put a fixed value on the variable a to illustrate, but you can use input() hassle-free.


"Wrong solutions"

Heed, if you don’t use split, each digit shall be considered individually:

a = '12 3 2 5343'
# código sem split, cada dígito é considerado um elemento separado da lista
x = sorted(int(n) for n in a if n.isdigit())
print(x)

This prints:

[1, 2, 2, 3, 3, 3, 4, 5]

This is because when iterating a string, every iteration the value of n will be a single character. To avoid this problem and consider numbers with more than one digit correctly, use split as already indicated.

And if you use split but not use int to convert to numbers, the values will be all strings, so they will be sorted according to the lexicographical order ("alphabetic"):

a = '12 3 2 5343'
# código com split, mas não usa int() para transformar os elementos em número
x = sorted(n for n in a.split(' ') if n.isdigit())
print(x) # ['12', '2', '3', '5343']

The result is ['12', '2', '3', '5343']. Note that the numbers are shown in quotes, indicating that they are actually strings (since I didn’t use int() to turn them into numbers). Therefore they are ordered according to the "alphabetical" order (which considers the unicode code points).

Only by turning the strings into numbers do you ensure that the correct order will be used.

The problem with these wrong "solutions" is that they "work" for simple cases, like 3 2 (or any other string that only has numbers with one digit). But if you have any number with more than one digit, they no longer work.


split multi-space

If the elements have more than one space separating them, just use the module re, which has a method split, only "turbine" (since it accepts any regular expression as a parameter):

import re

a = '12    3    2   5343'
x = sorted(int(n) for n in re.split(r'\s+', a) if n.isdigit())
print(x)

In case, I used the shortcut \s, which corresponds to space, TAB, line breaking and others (see documentation for more details). And using the quantifier +, i state that I want to be separated by one or more spaces. The result is:

[2, 3, 12, 5343]


Negative numbers

One detail is that isdigit() returns False for negative numbers:

print('-1'.isdigit()) # False

If you want to treat negative numbers, an alternative is to make a function that tries to convert list elements to number (using int), and if you can’t, ignore:

def converte(lista):
    for elemento in lista:
        try:
            # tenta converter para número
            yield int(elemento)
        except ValueError:
            pass # não é número, ignora

a = '12    3    -2   5343 aasdfasd'
x = sorted(n for n in converte(re.split(r'\s+', a)))
print(x)

In that case I don’t need to wear it anymore isdigit(), because the verification is done within the function converte. When the element is not a number, the function int() spear one ValueError, and simply ignore the element (as was the case with the element aasdfasd). The result is:

[-2, 3, 12, 5343]

-1

Friend, you have a much easier solution!

a = input()
x = a.replace(' ', '') # <- Remove os espaços!
print(sorted(x))

Dai vc tbm can transform to int again:

x = int(x)
  • 1

    It won’t work because you don’t consider numbers with more than one digit. If I enter "12 10 11" I would expect the answer "10, 11, 12", but your solution would bring "0, 1, 1, 1, 1, 2", which would make no sense.

  • Besides what Anderson said, if the input is the string 3 2 (i.e., numbers 3 and 2), the last line of the code results in number 32, which makes no sense: https://ideone.com/5xlzNt

Browser other questions tagged

You are not signed in. Login or sign up in order to post.