views:

1136

answers:

4

Using this question as the base is there an alogrithm or coding example to change some text to Pascal or Camel casing.

For example:

mynameisfred

becomes

Camel: myNameIsFred
Pascal: MyNameIsFred
A: 

The only way to do that would be to run each section of the word through a dictionary.

"mynameisfred" is just an array of characters, splitting it up into my Name Is Fred means understanding what the joining of each of those characters means.

You could do it easily if your input was separated in some way, e.g. "my name is fred" or "my_name_is_fred".

Mark Ingram
A: 

Short of trying to split it by words in a dictionary and treating all unrecognized character sequences as words... I can't think of anything efficient.

Allain Lalonde
+3  A: 

I found a thread with a bunch of Perl guys arguing the toss on this question over at http://www.perlmonks.org/?node_id=336331.

I hope this isn't too much of a non-answer to the question, but I would say you have a bit of a problem in that it would be a very open-ended algorithm which could have a lot of 'misses' as well as hits. For example, say you inputted:-

camelCase("hithisisatest");

The output could be:-

"hiThisIsATest"

Or:-

"hitHisIsATest"

There's no way the algorithm would know which to prefer. You could add some extra code to specify that you'd prefer more common words, but again misses would occur (Peter Norvig wrote a very small spelling corrector over at http://norvig.com/spell-correct.html which might help algorithm-wise, I wrote a C# implementation at http://www.codegrunt.co.uk/?page=cSharp#norvigSpell if C#'s your language).

I'd agree with Mark and say you'd be better off having an algorithm that takes a delimited input, i.e. this_is_a_test and converts that. That'd be simple to implement, i.e. in pseudocode:-

SetPhraseCase(phrase, CamelOrPascal):
    if no delimiters
     if camelCase
      return lowerFirstLetter(phrase)
     else
      return capitaliseFirstLetter(phrase)
    words = splitOnDelimiter(phrase)
    if camelCase 
      ret = lowerFirstLetter(first word) 
     else
      ret = capitaliseFirstLetter(first word)
    for i in 2 to len(words): ret += capitaliseFirstLetter(words[i])
    return ret

capitaliseFirstLetter(word):
    if len(word) <= 1 return upper(word)
    return upper(word[0]) + word[1..len(word)]

lowerFirstLetter(word):
    if len(word) <= 1 return lower(word)
    return lower(word[0]) + word[1..len(word)]

You could also replace my capitaliseFirstLetter() function with a proper case algorithm if you so wished.

A C# implementation of the above described algorithm is as follows (complete console program with test harness):-

using System;

class Program {
  static void Main(string[] args) {

    var caseAlgorithm = new CaseAlgorithm('_');

    while (true) {
      string input = Console.ReadLine();

      if (string.IsNullOrEmpty(input)) return;

      Console.WriteLine("Input '{0}' in camel case: '{1}', pascal case: '{2}'",
        input,
        caseAlgorithm.SetPhraseCase(input, CaseAlgorithm.CaseMode.CamelCase),
        caseAlgorithm.SetPhraseCase(input, CaseAlgorithm.CaseMode.PascalCase));
    }
  }
}

public class CaseAlgorithm {

  public enum CaseMode { PascalCase, CamelCase }

  private char delimiterChar;

  public CaseAlgorithm(char inDelimiterChar) {
    delimiterChar = inDelimiterChar;
  }

  public string SetPhraseCase(string phrase, CaseMode caseMode) {

    // You might want to do some sanity checks here like making sure
    // there's no invalid characters, etc.

    if (string.IsNullOrEmpty(phrase)) return phrase;

    // .Split() will simply return a string[] of size 1 if no delimiter present so
    // no need to explicitly check this.
    var words = phrase.Split(delimiterChar);

    // Set first word accordingly.
    string ret = setWordCase(words[0], caseMode);

    // If there are other words, set them all to pascal case.
    if (words.Length > 1) {
      for (int i = 1; i < words.Length; ++i)
        ret += setWordCase(words[i], CaseMode.PascalCase);
    }

    return ret;
  }

  private string setWordCase(string word, CaseMode caseMode) {
    switch (caseMode) {
      case CaseMode.CamelCase:
        return lowerFirstLetter(word);
      case CaseMode.PascalCase:
        return capitaliseFirstLetter(word);
      default:
        throw new NotImplementedException(
          string.Format("Case mode '{0}' is not recognised.", caseMode.ToString()));
    }
  }

  private string lowerFirstLetter(string word) {
    return char.ToLower(word[0]) + word.Substring(1);
  }

  private string capitaliseFirstLetter(string word) {
    return char.ToUpper(word[0]) + word.Substring(1);
  }
}
kronoz
+2  A: 

Childish I know, but how would you handle a string like sockettoopenisset?

toolkit