Split a character string based on change of character

From Rosetta Code
Split a character string based on change of character is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Split a (character) string into comma (plus a blank) delimited strings based on a change of character   (left to right).

Show the output here   (use the 1st example below).


Blanks should be treated as any other character   (except they are problematic to display clearly).   The same applies to commas.


For instance, the string:

 gHHH5YY++///\ 

should be split and show:

 g, HHH, 5, YY, ++, ///, \ 



Haskell

<lang Haskell>import Data.List (group, intercalate)

main :: IO () main = putStrLn $ intercalate ", " (group "gHHH5YY++///\\")</lang>

Output:
g, HHH, 5, YY, ++, ///, \

JavaScript

Translation of: Haskell

ES6

<lang JavaScript>(() => {

   'use strict';
   // GENERIC FUNCTIONS
   // group :: Eq a => [a] -> a
   const group = xs => groupBy((a, b) => a === b, xs);
   // groupBy :: (a -> a -> Bool) -> [a] -> a
   const groupBy = (f, xs) => {
       const lng = xs.length;
       if (lng > 0) {
           const x = xs[0],
               lstSpanRest = span(y => f(x, y), xs.slice(1)),
               ys = lstSpanRest[0],
               zs = lstSpanRest[1],
               group = [(ys.length ? [x].concat(ys) : [x])];
           return zs.length ? group.concat(groupBy(f, zs)) : group;
       } else return [];
   };
   // Span of unbroken predicate matches at left, returned with remainder
   //  span :: (a -> Bool) -> [a] -> ([a],[a])
   const span = (f, xs) => {
       for (var i = 0, lng = xs.length;
           (i < lng) && f(xs[i]); i++) {}
       return [xs.slice(0, i), xs.slice(i)];
   }
   // intercalate :: String -> [a] -> String
   const intercalate = (s, xs) => xs.join(s);


   // TEST
   return intercalate(", ", group("gHHH5YY++///\\".split())
       .map(x => x.join()));
   // -> "g, HHH, 5, YY, ++, ///, \\"

})();</lang>

Output:
g, HHH, 5, YY, ++, ///, \

Python

<lang python>import itertools

try: input = raw_input except: pass

s = input() groups = [] for _, g in itertools.groupby(s):

   groups.append(.join(g))

print(' input string: %s' % s) print(' output string: %s' % ', '.join(groups))</lang>

Output:

  when using the default input

      input string:  gHHH5YY++///\
     output string:  g, HHH, 5, YY, ++, ///, \

REXX

<lang rexx>/*REXX program splits a string based on change of character ───► a comma delimited list.*/ parse arg str . /*obtain optional arguments from the CL*/ if str== | str=="," then str= 'gHHH5YY++///\' /*Not specified? Then use the default.*/ p=left(str, 1) /*placeholder for the "previous" string*/ $= /* " " " output " */

     do j=1  for length(str);      @=substr(str, j, 1)    /*obtain a char from string. */
     if @\==left(p, 1)   then do;  $=$',' @;  p=;  end    /*different then previous?   */
                         else      $=$ || @               /*a replicated character.    */
     p=p || @                                             /*append char to current list*/
     end   /*j*/

say ' input string: ' str say ' output string: ' $ /*stick a fork in it, we're all done. */</lang> output   when using the default input:

      input string:  gHHH5YY++///\
     output string:  g, HHH, 5, YY, ++, ///, \