2
\$\begingroup\$

So, another challenge from my professor. I've finished it, but wanted to get some feedback, and see how other people might work this problem.

Assume you have a string, such as "Hello 34215 World 5620 From 384 Bloomington"

Use list comprehension to separate the words from the numbers, and the numbers from the words. Then order the numbers from smallest to largest. Print out these words and numbers separated by a "|". The output for the example given above would be:

>>>
Hello World From Bloomington | 012233445568

The challenge is to write the code in two lines, one of the lines being the definition of the string.

This is what I wrote:

string = "Hello 34215 World 5620 From 384 Bloomington"
print str(" | ".join(["".join([letter for letter in string if letter.isalpha() or letter.isspace()]), "".join(sorted([num for num in string if num.isdigit()]))])).replace("  ", " ")

It works! The output is identical to the output displayed. But, I'd love to hear feedback about how this is done, or if there are any pieces of redundant code, etc. I don't use lambda, map, set, etc. nor do I import any libraries, but if you find that there is a way to do it with any of those pieces, feel free to share!

\$\endgroup\$

migrated from stackoverflow.com Jul 1 '14 at 3:13

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ "".join(x for x in s if not x.isdigit()) +" | "+ "".join(sorted(x for x in s if x.isdigit() )) \$\endgroup\$ – Padraic Cunningham Jun 30 '14 at 23:42
  • \$\begingroup\$ @Padraic Cunningham The issue with that line is that there are two spaces between each word. I found I had that issue before, and had to change some of my code to fix it. \$\endgroup\$ – brettwbyron Jun 30 '14 at 23:45
  • 2
    \$\begingroup\$ " ".join(x for x in s.split() if not x.isdigit()) +" | "+ "".join(sorted(x for x in s if x.isdigit() )) \$\endgroup\$ – Padraic Cunningham Jul 1 '14 at 0:01
  • 2
    \$\begingroup\$ From the description, I really would have expected the right output to be Hello World From Bloomington | 384 5620 34215. \$\endgroup\$ – user2357112 Jul 1 '14 at 3:18
  • \$\begingroup\$ @user2357112 The description is paraphrased. \$\endgroup\$ – brettwbyron Jul 1 '14 at 17:03
1
\$\begingroup\$

Padraic Cunningham nailed the shortest form in his comment:

" ".join(x for x in s.split() if not x.isdigit()) + " | " + "".join(sorted(x for x in s if x.isdigit()))

Explanation:

  • x for x in s.split() if not x.isdigit() -- the list of words that don't have digits. Note that the split method without parameters uses space as the separator.
  • x for x in s if x.isdigit() -- the list of digits extracted from the string, unsorted
  • From the above 2 it's easy to combine to get the desired result.

Although this is short, it checks every letter twice, first using not x.isdigit() to get only the letters and then x.isdigit() to get only the digits. We could improve that by using a helper function to partition the list of words on the outcome of x.isdigit(), like this:

def partition(pred, iterable):
    trues = []
    falses = []
    for item in iterable:
        if pred(item):
            trues.append(item)
        else:
            falses.append(item)
    return trues, falses

nums, words = partition(str.isdigit, s.split())
' '.join(words) + ' | ' + ''.join(sorted(''.join(nums)))

Of course, this is much more than one line...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.