Stripping off extra spaces from a string

12

2

You are given a string. Output the string with one space per words.

Challenge

Input will be a string (not null or empty), surrounded with quotes(") sent via the stdin. Remove leading and trailing spaces from it. Also, if there are more than one space between two words (or symbols or whatever), trim it to just one space. Output the modified string with the quotes.

Rules

  • The string will not be longer than 100 characters and will only contain ASCII characters in range (space) to ~(tilde) (character codes 0x20 to 0x7E, inclusive) except ",i.e, the string will not contain quotes(") and other characters outside the range specified above. See ASCII table for reference.
  • You must take input from the stdin( or closest alternative ).
  • The output must contain quotes(").
  • You can write a full program, or a function which takes input (from stdin), and outputs the final string

Test Cases

"this  is  a    string   "         --> "this is a string"

"  blah blah    blah "             --> "blah blah blah"

"abcdefg"                          --> "abcdefg"

"           "                      --> ""

"12 34  ~5 6   (7, 8) - 9 -  "     --> "12 34 ~5 6 (7, 8) - 9 -" 

Scoring

This is code golf, so the shortest submission (in bytes) wins.

Spikatrix

Posted 2015-05-20T15:16:04.547

Reputation: 1 663

1You say must take input from stdin, and later you say ...or a function which takes input, and outputs the final string. Does this mean the function must take input from stdin as well? – blutorange – 2015-05-20T15:35:08.720

@blutorange , Yes. Edited to clarify it. – Spikatrix – 2015-05-20T15:36:30.760

2" "aa" " --> ""aa"" (are quotes valid inside the input string?) – edc65 – 2015-05-20T15:36:36.707

@edc65 , Good point. The answer to that is no. Edited to clarify it. – Spikatrix – 2015-05-20T15:51:37.620

Please see MickeyT's comment on my answer. Is what he proposes valid? In R, returned results are implicitly printed, but in my answer I've explicitly printed to stdout.

– Alex A. – 2015-05-20T19:30:04.603

@AlexA. , The output needs to be seen in the stdout. It doesn't matter if it is implicitly or explicitly printed. – Spikatrix – 2015-05-21T08:40:14.960

Some answers are processing string including the double quotes: "   this  ", others process a once double quoted string which reaches the code with the double quotes already stripped off: this. This way the answers and the languages'/authors' efficiencies are not really comparable. @CoolGuy, could you firmly clarify the requirement on this? – manatwork – 2015-05-22T10:49:23.977

@manatwork , I don't know. Do many answers take advantage of it? If so, I think it is better to leave both ways permitted. – Spikatrix – 2015-05-23T06:49:23.530

@CoolGuy, yeah, now that we already have 20 answers, is indeed a bit late to impose a restriction. Though in my opinion this way the challenge is ruined. :( – manatwork – 2015-05-23T13:58:52.387

Answers

12

CJam, 7 bytes

q~S%S*p

Code Explanation

CJam has reserved all capital letters as inbuilt variables. So S has a value of a space here.

q~          e# Read the input (using q) and evaluate (~) to get the string
  S%        e# Split on running lengths (%) of space
    S*      e# Join (*) the splitted parts by single space
      p     e# Print the stringified form (p) of the string.

This removes the trailing and leading spaces as well

Try it online here

Optimizer

Posted 2015-05-20T15:16:04.547

Reputation: 25 836

10

///: 18 characters

/  / //" /"// "/"/

Sample run:

(Using faubiguy's interpreter from his Perl answer for Interpret /// (pronounced 'slashes').)

bash-4.3$ ( echo -n '/  / //" /"// "/"/'; echo '"   foo  *  bar   "'; ) | slashes.pl
"foo * bar"

manatwork

Posted 2015-05-20T15:16:04.547

Reputation: 17 865

11Haven't I seen this program somewhere before? – r3mainer – 2015-05-20T17:48:59.257

Technically you're not taking input though. ;) There's this language but reading input is still quite a pain I think.

– Martin Ender – 2015-05-20T22:00:52.660

6

Perl, 22

(20 bytes of code, plus 2 command line switches)

s/ +/ /g;s/" | "/"/g

Needs to be run with the -np switch so that $_ is automatically filled via stdin and printed to stdout. I'm going to assume this adds 2 to the byte count.

r3mainer

Posted 2015-05-20T15:16:04.547

Reputation: 19 135

1same solution: sed -E 's/ +/ /g;s/" | "/"/g' – izabera – 2015-05-20T16:01:33.877

3

The same thing is 12 bytes in Retina. :)

– Martin Ender – 2015-05-20T16:24:30.143

-p implies -n, so you only have to take a +1 penalty here (assuming you don't just switch to a different language, like the other commenters suggest). – None – 2016-12-18T08:44:43.783

4

Pyth, 17 15 11 10 bytes

(thanks to Ypnypn and FryAmTheEggman)

pjd-cQdkNN

Could probably be golfed more.

If the output can use ' instead of " then I only need 8 bytes:

`jd-cQdk

Tyilo

Posted 2015-05-20T15:16:04.547

Reputation: 1 372

You can use N instead of \" – Ypnypn – 2015-05-21T00:23:36.427

Welcome to Pyth, Tylio. The second program could be shorterned by the use of d. – isaacg – 2015-05-21T07:29:10.223

@isaacg haven't I already used d for everything it can be used for? – Tyilo – 2015-05-22T23:38:04.130

@Tyilo I think you made an edit at about the same time I commented. It's all good now. – isaacg – 2015-05-22T23:48:36.097

You can use p to save a few bytes on string concatenation instead of many +es. pjd-cQdkNN – FryAmTheEggman – 2015-05-23T03:38:29.383

Oh, I also happened upon this: pjdcQ)NN. It turns out the no-argument version of c (hence closing it with a ) ) automatically strips out excess spaces. – FryAmTheEggman – 2015-05-24T14:43:19.323

4

Ruby, 31 29 25 23 Bytes

p$*[0].strip.squeeze' '

Code Explanation:

  • p outputs string within double quotes to STDOUT (There's more to it though...)
  • $* is an array of STDIN inputs, $*[0] takes the first one
  • strip removes starting and ending spaces
  • squeeze ' ' replaces >1 space characters with a single space

Test Cases:

enter image description here

Sheharyar

Posted 2015-05-20T15:16:04.547

Reputation: 651

1You can replace ARGV with $* saving two bytes. gsub /\s+/, ' ' can be replaced with squeeze ' ' for another 4 bytes – DickieBoy – 2015-05-22T09:57:41.557

@DickieBoy, thank you for $*, I didn't know that. But we can't replace gsub /\s+/, ' ' with squeeze because they are not the same.

– Sheharyar – 2015-05-22T10:09:40.383

What do you mean by "are not the same"? The outputs are the same. – DickieBoy – 2015-05-22T10:16:01.823

Well, they aren't. gsub /\s+/, ' ' replaces >1 'space characters' with a single space character, on the other hand squeeze replaces any character >1 with a single one. – Sheharyar – 2015-05-22T10:20:09.520

Example: "yellow moon".squeeze #=> "yelow mon" – Sheharyar – 2015-05-22T10:20:14.980

1squeeze ' ' will only squeeze spaces. "yellow moon".squeeze "l" => "yelow moon" – DickieBoy – 2015-05-22T10:24:09.080

Your inputs are wrong, they should contain the surrounding double quotes: ./codegolf.rb '"this  is  a    string   "'. The quotes as you have them in your sample run are stripped off by the shell, so they never reach Ruby. – manatwork – 2015-05-22T10:26:54.160

@DickieBoy Oh nice. Thanks! – Sheharyar – 2015-05-22T10:28:31.307

@manatwork Are you sure that's what OP meant? I can update code, it would be shorter for that. The challenge says "Input will be a string (not null or empty), surrounded with quotes(") sent via the stdin." and the first rule says "the string will not contain quotes(")" – Sheharyar – 2015-05-22T10:37:40.623

2Personally I am. And some of other answerers too. But as I see, neither you are alone with your interpretation… A clarification from the question owner would be welcome. By the way, both the space between p and its parameter and squeeze and its parameter are unnecessary. – manatwork – 2015-05-22T10:42:53.813

@manatwork Fuck! I didn't know that was possible! Thank you so much! – Sheharyar – 2015-05-22T11:18:51.887

3

Haskell, 31 25 bytes

fmap(unwords.words)readLn

words splits the string into a list of strings with spaces as delimiters and unwords joins the list of strings with a single spaces in-between. The quotes " are stripped of and put back by Haskell's read and show (implicitly via the REPL) functions on strings.

Outputting by the function itself is three bytes longer, i.e. 28 bytes:

print.unwords.words=<<readLn

Edit: @Mauris pointed to the readLn function, which saved some bytes.

nimi

Posted 2015-05-20T15:16:04.547

Reputation: 34 639

I'm getting Parse error: naked expression at top level when I tested both the codes here

– Spikatrix – 2015-05-21T08:45:17.610

@CoolGuy: rextester.com expects whole programs, not functions, so try main=interact$show.unwords.words.read. There's an online REPL at the frontage of http://haskell.org (requires cookies enabled) where you can try fmap(unwords.words.read)getLine.

– nimi – 2015-05-21T14:19:55.183

1fmap(unwords.words)readLn and print.unwords.words=<<readLn are a bit shorter. – Lynn – 2015-05-23T01:38:33.930

@Mauris: thanks for pointing to readLn. – nimi – 2015-05-23T08:31:58.843

3

Bash, 36 32 bytes

As a function, a program, or just in a pipe:

xargs|xargs|xargs -i echo '"{}"'

Explanation

The first xargs strips the quotation marks.

The second xargs trims the left side and replaces multiple adjacent spaces in the middle of the string with one space by taking each "word" and separating each with a space.

The xargs -i echo '"{}"' trims the right side and rewraps the resulting string in double quotes.

Deltik

Posted 2015-05-20T15:16:04.547

Reputation: 131

2Wow! That is tricky. Unfortunately not handles test case 4, but still impressing. – manatwork – 2015-05-21T07:46:09.753

Yeah, this code meets the fourth test case and is shorter.

– Deltik – 2015-05-21T10:27:47.033

Can you do something like this? x=xargs;$x|$x|$x -i echo '"{}"' – Cyoce – 2017-09-01T05:09:57.440

@Cyoce: You could indeed do that to save one byte at the cost of losing pipe functionality. Still not as short as this solution and still doesn't satisfy the fourth test case.

– Deltik – 2017-09-01T07:44:21.653

2

05AB1E, 9 bytes

#õKðý'".ø

Try it online!


#         | Split on spaces.
 õK       | Remove empty Strings.
   ðý     | Join with spaces.
     '".ø | Surround with quotes.

Magic Octopus Urn

Posted 2015-05-20T15:16:04.547

Reputation: 19 422

2

JavaScript (ES6), 49 52 58

Edit 6 bytes shorter, thanks to @Optimizer

Edit 2 -3, thanks to @nderscore

Input/output via popup. Using template string to cut 1 byte in string concatenation.

Run snippet to test in Firefox.

alert(`"${prompt().match(/[^ "]+/g).join(" ")}"`)

edc65

Posted 2015-05-20T15:16:04.547

Reputation: 31 086

alert(\"${eval(prompt()).match(/\S+/g).join(" ")}"`)` - 52 – Optimizer – 2015-05-20T15:50:45.683

@Optimizer thx. Note, that just works after the last clarification about the quotes: eval('" " "') would crash. – edc65 – 2015-05-20T15:55:43.380

When I tested the fourth test case (using chrome), no popup (which shows the result) is seen. Why? – Spikatrix – 2015-05-21T08:42:36.337

@CoolGuy maybe because Chrome does not run ES6? I never test ES6 with Chrome. Anyway I tried it now in my Chrome (42.0.2311.152) and works for me. – edc65 – 2015-05-21T10:49:46.027

-3: alert(\"${prompt().match(/[^ "]+/g).join(" ")}"`)` – nderscore – 2015-05-23T15:54:35.833

@CoolGuy If you are using the console with chrome make sure to not have the devtools in a separate window. since chrome blocks all prompts that don't come from the currently active tab. – Brian H. – 2017-09-22T06:55:16.110

" " " " - is that a valid input? – Qwertiy – 2019-08-26T17:05:38.860

@Qwertiy the string will not contain quotes(") so, no, it's not – edc65 – 2019-08-26T18:36:05.103

2

Python2, 37

Reduced by 1 byte thanks to @ygramul.

print'"%s"'%' '.join(input().split())

Original version:

print'"'+' '.join(input().split())+'"'

Test cases:

Test cases screenshot

user12205

Posted 2015-05-20T15:16:04.547

Reputation: 8 752

I really wanted to use print" ".join(raw_input().split()), but it would have a trailing space inside the last quotation mark if there were spaces after the last word... – mbomb007 – 2015-05-20T19:24:09.593

You can shave off an extra byte using % formatting: print'"%s"'%' '.join(input().split()) – ygramul – 2015-05-22T15:26:28.180

2

R, 45 bytes

cat('"',gsub(" +"," ",readline()),'"',sep="")

The readline() function reads from STDIN, automatically stripping any leading and trailing whitespace. Excess space between words is removed using gsub(). Finally, double quotes are prepended and appended and the result is printed to STDOUT.

Examples:

> cat('"',gsub(" +"," ",readline()),'"',sep="")
    This   is     a   string  
"This is a string"

> cat('"',gsub(" +"," ",readline()),'"',sep="")
12 34  ~5 6   (7, 8) - 9 -  
"12 34 ~5 6 (7, 8) - 9 -"

Alex A.

Posted 2015-05-20T15:16:04.547

Reputation: 23 761

Not sure if it complies totally with the rules, but the cat may not be totally required, just the gsub. The output from that is [1] "This is a string" – MickyT – 2015-05-20T19:26:26.230

@MickyT: Thanks for the suggestion. My interpretation based on the OP's comment (first on the post) was that it had to be printed to stdout. I'll ask for clarification. – Alex A. – 2015-05-20T19:28:43.003

Ahhh ... didn't see that comment or requirement – MickyT – 2015-05-20T19:30:34.997

1

Japt -Q, 10 4 bytes

¸f ¸

Try it

Shaggy

Posted 2015-05-20T15:16:04.547

Reputation: 24 623

1

Java 8, 43 bytes

s->'"'+s.replaceAll(" +|\""," ").trim()+'"'

Explanation:

Try it here.

s->                           // Method with String as parameter and return-type
  '"'                         //  Return a leading quote
  +s.replaceAll(" +           //  + Replace all occurrences of multiple spaces
                   |\"",      //     and all quotes
                        " ")  //    with a single space
    .trim()                   //  And remove all leading and trailing spaces
  +'"'                        //  And add the trailing quote
                              // End of method (implicit / single-line return statement)

Kevin Cruijssen

Posted 2015-05-20T15:16:04.547

Reputation: 67 575

1

Octave, 44 bytes

@(x)[34 strjoin(regexp(x,'\S+','match')) 34]

Try it online!

Luis Mendo

Posted 2015-05-20T15:16:04.547

Reputation: 87 464

1

Tcl, 69 bytes

puts [string map {{ "} \" {" } \"} [regsub -all \ + [gets stdin] \ ]]

Try it online!

Tcl, 79 bytes

puts \"[string trim [regsub -all \ + [string range [gets stdin] 1 end-1] \ ]]\"

Try it online!

sergiol

Posted 2015-05-20T15:16:04.547

Reputation: 3 055

@KevinCruijssen Fixed. unfortunately, at the expense of many bytes. Tks for telling me. – sergiol – 2017-09-22T22:25:54.373

1

Jq 1.5, 42 bytes

split(" ")|map(select(length>0))|join(" ")

Sample Run

$ jq -M 'split(" ")|map(select(length>0))|join(" ")' < data
"this is a string"
"blah blah blah"
"abcdefg"
""
"12 34 ~5 6 (7, 8) - 9 -"

$ echo -n 'split(" ")|map(select(length>0))|join(" ")' | wc -c
  42

Try it online

jq170727

Posted 2015-05-20T15:16:04.547

Reputation: 411

I caught the output issue earlier (see edit 5) but didn't notice the input issue. The command is fixed now. Thanks! – jq170727 – 2017-09-22T14:30:33.377

1

Perl 5, 17 bytes

16 bytes of code + 1 for -p

s/ *("| ) */$1/g

Try it online!

Xcali

Posted 2015-05-20T15:16:04.547

Reputation: 7 671

1

Mathematica, 75 bytes

a=" ";b=a...;Print[InputString[]~StringReplace~{b~~"\""~~b->"\"",a..->a}]

LegionMammal978

Posted 2015-05-20T15:16:04.547

Reputation: 15 731

1

KDB(Q), 28 bytes

" "sv except[;enlist""]" "vs

Explanation

                       " "vs    / cut string by space
      except[;enlist""]         / clear empty strings
" "sv                           / join back with space

Test

q)" "sv except[;enlist""]" "vs"12 34  ~5 6   (7, 8) - 9 -  "
"12 34 ~5 6 (7, 8) - 9 -"

WooiKent Lee

Posted 2015-05-20T15:16:04.547

Reputation: 413

0

Powershell, 40 bytes

"`"$(($args-Replace' +'," ").trim())`""

Pretty straight forward and not very impressive.

Explanation

Take input parameter via (predfined) args-variable, replace all multiple spaces with one, trim leading and trailing spaces using trim()-method, add quotes. Powershell will print strings to console as default behavior.

whatever

Posted 2015-05-20T15:16:04.547

Reputation: 161

0

k4, 23 bytes

" "/:x@&~~#:'x:" "\:0:0

                    0:0  / read from stdin
             x:" "\:     / split string on spaces and assign to x
        ~~#:'            / boolean true where string len>0, bool false otherwise
     x@&                 / x at indices where true
" "/:                    / join with spaces

scrawl

Posted 2015-05-20T15:16:04.547

Reputation: 1 079

0

Zsh, 15 bytes

<<<\"${(Qz)1}\"

Try it online!

Input string contains embedded quotes. Remove the Q for 14 bytes if the input string does not contain embedded quotes, as is done in some of the other answers here.

Parameter expansion flags: Q dequotes, then z splits into words as the shell does. The words are then implicitly joined by spaces.

GammaFunction

Posted 2015-05-20T15:16:04.547

Reputation: 2 838

0

Wren, 56 bytes

Wait. The replace only does it once? Now I have to use the split-join combo.

Fn.new{|x|x.trim().split(" ").where{|i|i!=""}.join(" ")}

Try it online!

Explanation

Fn.new{|x|                                             } // New anonymous function with the operand x
          x.trim()                                       // Trim out whitespace from both sides of the string
                  .split(" ")                            // Split the string into space-separated chunks
                             .where{|i|i!=""}            // Keep all of those that aren't the null string (due to two consecutive spaces)
                                             .join(" ")  // Join the replaced list together

user85052

Posted 2015-05-20T15:16:04.547

Reputation:

0

GolfScript, 8 bytes

' '%' '*

Try it online!

Explanation

The logic is quite simple:

' '%     # Split on spaces, remove empty results
    ' '* # Join on spaces

user85052

Posted 2015-05-20T15:16:04.547

Reputation:

0

golfua, 42 bytes

L=I.r():g('%s*\"%s*','"'):g('%s+',' ')w(L)

Simple pattern matching replacement: find any double quotes (\") surrounded by 0 or more spaces (%s*) & return the single quote, then replace all 1 or more spaces (%s+) with a single space.

A Lua equivalent would be

Line = io.read()
NoSpaceQuotes = Line:gsub('%s*\"%s*', '"')
NoExtraSpaces = NoSpaceQuotes:gsub('%s+', ' ')
print(NoExtraSpaces)

Kyle Kanos

Posted 2015-05-20T15:16:04.547

Reputation: 4 270

0

Cobra - 68

As an anonymous function:

do
    print'"[(for s in Console.readLine.split where''<s).join(' ')]"'

Οurous

Posted 2015-05-20T15:16:04.547

Reputation: 7 916

0

Objective-C 215

-(NSString*)q:(NSString*)s{NSArray*a=[s componentsSeparatedByString:@" "];NSMutableString*m=[NSMutableString new];for(NSString*w in a){if(w.length){[m appendFormat:@"%@ ",w];}}return[m substringToIndex:m.length-1];}

Uncompressed version:

-(NSString*)q:(NSString*)s{
    NSArray *a=[s componentsSeparatedByString:@" "];
    NSMutableString *m=[NSMutableString new];
    for (NSString *w in a) {
        if (w.length) {
            [m appendFormat:@"%@ ",w];
        }
    }
    return[m substringToIndex:m.length-1];
}

Fennelouski

Posted 2015-05-20T15:16:04.547

Reputation: 121

0

Bash ,14 bytes

read f;echo $f       # assume f="this  is  a    string   "

michael501

Posted 2015-05-20T15:16:04.547

Reputation: 191

1What about assuming “   foo   *   bar   ” or anything else with a wildcard character? – manatwork – 2015-05-23T14:01:55.590

-1

Python2, 28 Bytes

lambda s:" ".join(s.split())

Explanation

lambda s

Anonymous function which takes as input s.

s.split()

Returns a list of the words (which are separated by arbitrary strings of whitespace characters) of the string s.

" ".join(...)

Joins list back into a string, with each word separated by a space (" ").

Triggernometry

Posted 2015-05-20T15:16:04.547

Reputation: 765

2This seems to give incorrect results regarding leading and trailing spaces. Note that the challenge state you should take the input with the double-quotes, and also output them with double-quotes. I also had this wrong at first, until I re-read the challenge. – Kevin Cruijssen – 2017-09-01T10:28:42.987