0

I want to make a program which takes a string you entered and turn it to different string, so if for example I input "Hello World" every char will turn into a string and the console will output something like "Alpha Beta Gamma Gamma Zeta Foxtrot Dona Rama Lana Zema" - making every char a word.

I tried doing it like this :

static string WordMap(string value)
{
    char[] buffer = value.ToCharArray();
    for (int i = 0; i < buffer.Length; i++)
    {
        if (letter = "a")
        {
            letter = ("Alpha");
        }
        //and so on

        buffer[i] = letter;

    }

    return new string(buffer);           

}

but I just can't get it to work. can anyone give me a tip or point me at the right direction?

2
  • 1
    who is letter? your code, as shown, does not compile Commented Jan 31, 2014 at 12:38
  • 3
    Consider a Dictionary<char, String>... Commented Jan 31, 2014 at 12:40

7 Answers 7

5

What you need is a Dictionary<char,string>

var words = new Dictionary<char, string>();
words.Add('a', "Alpha");
words.Add('b',"Beta");
...
string input = Console.ReadLine();
string[] contents = new string[input.Length];
for (int i = 0; i < input.Length; i++)
{
     if (words.ContainsKey(input[i]))
     {
         contents[i] = words[input[i]];
     }
}
string result = string.Join(" ", contents);

Or LINQ way:

var result = string.Join(" ", input.Where(words.ContainsKey).Select(c => words[c]));
Sign up to request clarification or add additional context in comments.

6 Comments

Or just use LINQ: string result = string.Join(" ", input.Select(c => words[c]));
@JonSkeet exactly :) but still we should use ContainsKey to prevent KeyNotFoundExceptin I guess
Potentially. It depends on what you want the failure mode to be :) It would be reasonably simple to add that in though: input.Where(c => words.ContainsKey(c)).Select(...). Oh, and you can use a collection initializer to make the dictionary initialization much cleaner.
This way poor guy will not learn, you put too much magic on someone who struggle with comparing characters... Linq ...
@Mateusz: If I'd written an answer, I wouldn't have gone straight to LINQ - but it's good to show what the result can look like, and how to get there.
|
1

First off, the buffer is a char array. Arrays have a fixed size and to expand them you need to create a new one. To overcome this cumbersome work, there is a StringBuilder class that does this automatically.

Secondly, if you keep these 'Alpha', 'Beta', ... strings in if statements you will have a very long piece of code. You can replace this by using a dictionary, or create it from a single string or text file.

To put this into practice:

class MyClass
{
    static Dictionary<char, string> _map = new Dictionary<char, string>();

    static MyClass()
    {
        _map.Add('a', "Alpha");
        _map.Add('b', "Beta");
        // etc
    }

    static string WordMap(string data)
    {
        var output = new StringBuilder();
        foreach (char c in data)
        {
            if (_map.ContainsKey(c))
            {
                output.Append(_map[c]);
                output.Append(' ');
            }
        }
        return output.ToString();
    }
}

Solution without a dictionary:

static string WordMap(string data)
{
    const string words = "Alpha Beta Gamma Delta ...";

    string[] wordMap = words.Split(' ');

    var output = new StringBuilder();
    foreach (char c in data)
    {
        int index = c - 'a';
        if (index >= 0 && index < wordMap.Length)
        {
            output.Append(wordMap[index]);
            output.Append(' ');
        }
    }
    return output.ToString();
}

4 Comments

In your second piece of code I think you want your if statement to be if (index >= 0 && index < wordMap.Length)
thank you that is exactly what it tried to do, and i can see you really putted effort into this, not to speak of the quick response, so again, thanks a lot.
Also you should convert the character to lower case before looking it up in the dictionary or converting it to an index or this isn't going to work for upper case characters.
Assuming it is lower case; as the question does !
0

With LINQ and String.Join it's short and readable. Since you want to have a new word for special chards you need a word-map. I would use a Dictionary<char, string>:

static Dictionary<char, string> wordMap = new Dictionary<char, string>()
{
    {'a', "Alpha"}, {'b', "Beta"},{'c', "Gamma"}, {'d', "Delta"}
};

static string WordMap(string value)
{
    var strings = value
        .Select(c => 
        {
            string word; 
            if(!wordMap.TryGetValue(c, out word))
                word = c.ToString();
            return word;
        });
    return string.Join("", strings);
}

Test:

string newString = WordMap("abcdeghj");  // AlphaBetaGammaDeltaeghj

Comments

0

Tips: You don't have to create character array from string, you can easily access single characters in string by indexer:

char some = "123"[2];

When you use "" then you create string not char therefore you should use '' to create character for comparison:

if (some == 'a') Console.WriteLine("character is a, see how you compare chars!!!");

4 Comments

Why would you use ElementAt? You were berating my use of LINQ, but you're using the ElementAt extension method yourself!
@JonSkeet OP asked for tips, so I wanted to show him that he does not have to make char array. Second thing was that he try to compare character to string. It would simplify things for OP. This would leave learning about Dictionary and LINQ for later. I remember my first hard times with LINQ so I think person who ask such question doesn't need to go into it. But your point about demonstrating how it can be done is perfectly valid so I am not replying there.
So just show the indexer use - that makes sense. Using ElementAt is an odd approach and may well be an O(n) operation... I would remove it.
Fair enough, so I also elaborated on points I wanted to emphasise.
0

A good solution ...

    string[] words = { "Alpha", "Beta", "C_word", "D_Word" }; // ....

    string myPhrase = "aBC";

    myPhrase.Replace(" ", string.Empty).ToList().ForEach(a =>
    { 
        int asciiCode = (int)a;
        /// ToUpper()
        int index = asciiCode >= 97 ? asciiCode - 32 : asciiCode;
        Console.WriteLine(words[index - 65]); // ascii --> 65-a , 66-b ...
    });

Comments

0

One more variation of answer which contains not found option.

 static Dictionary<char, string> Mapping =
     new Dictionary<char, string>() 
         { { 'a', "alpha" }, { 'b', "beta" }, { 'c', "gamma" }, { 'd', "zeta" } };

    static void Main(string[] args)
    {            
        string test = "abcx";
        Console.WriteLine(string.Join(" ", test.Select(t => GetMapping(t))));  
        //output alpha beta gamma not found         
        Console.ReadKey();
    }

    static string GetMapping(char key)
    {
        if (Mapping.ContainsKey(key))
            return Mapping.First(a => a.Key == key).Value;
        else
            return "not found";            
    }      

Comments

-1

Just declare a second variable where you build up your result. And I think you have some syntax problems, you need to have "==" in a condition, otherwise it's an assignment.

static string WordMap(string value)
{
      string result = string.Empty;
      char[] buffer = value.ToCharArray();
      for (int i = 0; i < buffer.Length; i++)
      {
          if (letter == "a")
          {
              result += ("Alpha");
          }
          //and so on            

       }

       return result;           
 }

But I would only do this that way, if this is "just for fun" code, as it will not be very fast. Building up the result like I did is slow, a better way would be

result = string.Concat(result, "(Alpha)");

And an even faster way is using a StringBuilder (s. documentation for that), which offers you fast and convenient methods to deal with bigger strings. Only downfall here is, that you need to know a little bit, how big the result will be in characters, as you need to provide a starting dimension. And here you should not start with simply 1, or 100. Each time, when the StringBuilder is full, it creates a new bigger instance and copies the values, so multiple instances of that will fill your memory, which can cause an out of memory exception, when dealing with some ten thousands of characters.

But as said, for just for fun code, all of that does not matter... And of course, you need to be aware, that if you do it like that, your result will be in one straight line, no breaks. If you want line breaks add "\n" at the end of the strings. Or add anything elese you need.

Regards,

Markus

2 Comments

Please explain how string.Concat(result, "(Alpha)"); is faster than result += ("Alpha");
Indeed. Using string.Join once would be faster, as would using StringBuilder. Suggesting repeated string.Concat calls suggests that you don't really understand why using += is slow. Please read pobox.com/~skeet/csharp/stringbuilder.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.