英语到PigLatin句子的转换

时间:2015-12-08 15:16:27

标签: c# string foreach indexof

我正在制作一个将英语转换为PigLatin的程序。但是,我的解决方案似乎只能用一个词。如果我输入的不仅仅是单词,则只翻译最后一个单词。

  

测试一个翻译

只需输出:

  

translationway

我已经看过一些解决方案了,但大多数都与我的方式相同,或者使用"简化"超出我所知范围的解决方案。

代码:

 static void Main(string[] args)
    {
        Console.WriteLine("Enter a sentence to convert to PigLatin:");
        string sentence = Console.ReadLine();
        string pigLatin = ToPigLatin(sentence);
        Console.WriteLine(pigLatin);
    }

    static string ToPigLatin (string sentence)
    {            
        string firstLetter,
               restOfWord,
               vowels = "AEIOUaeio";
        int currentLetter;

        foreach (string word in sentence.Split())
        {
            firstLetter = sentence.Substring(0, 1);
            restOfWord = sentence.Substring(1, sentence.Length - 1);
            currentLetter = vowels.IndexOf(firstLetter);

            if (currentLetter == -1)
            {
                sentence = restOfWord + firstLetter + "ay";
            }
            else
            {
                sentence = word + "way";
            }
        }
        return sentence;

非常感谢所有帮助!

修改

感谢很多反馈,我已经更新了我的代码:

    static string ToPigLatin (string sentence)
    {

        const string vowels = "AEIOUaeio";
        List<string> pigWords = new List<string>();

        foreach (string word in sentence.Split(' '))
        {
            string firstLetter = word.Substring(0, 1);
            string restOfWord = word.Substring(1, word.Length - 1);
            int currentLetter = vowels.IndexOf(firstLetter);

            if (currentLetter == -1)
            {
                pigWords.Add(restOfWord + firstLetter + "ay");
            }
            else
            {
                pigWords.Add(word + "way");
            }
        }
        return string.Join(" ", pigWords);
    }

调整此代码以使用辅音群是否会非常复杂?

例如,现在测试一个翻译打印为:

  

estingtay oneway ranslationtay

虽然我理解PigLatin规则,但它应该是:

  

estingtay oneway anslationtray

3 个答案:

答案 0 :(得分:2)

在这里放置+=而不是=

if (currentLetter == -1)
{
    sentence += restOfWord + firstLetter + "ay";
}
else
{
    sentence += word + "way";
}

在你的版本中,你在循环的每次迭代中覆盖了句子

修改

我对代码进行了批次更改:

public static string ToPigLatin(string sentence)
{
    const string vowels = "AEIOUaeio";
    List<string> newWords = new List<string>();

    foreach (string word in sentence.Split(' '))
    {
        string firstLetter = word.Substring(0, 1);
        string restOfWord = word.Substring(1, word.Length - 1);
        int currentLetter = vowels.IndexOf(firstLetter);

        if (currentLetter == -1)
        {
            newWords.Add(restOfWord + firstLetter + "ay");
        }
        else
        {
            newWords.Add(word + "way");
        }
    }
    return string.Join(" ", newWords);
}

正如Panagiotis-Kanavos所说,他该死的,不要在输入 输入 因此,我添加了newWords列表(有些人可能更喜欢StringBuilder,我不喜欢)。

您在循环中滥用了变量,尤其是Substrings次调用,现在已经修复了。

如果您对此有任何疑问,请不要犹豫。

答案 1 :(得分:0)

 private static void Main(string[] args)
        {
            Console.WriteLine("Enter a sentence to convert to PigLatin:");
            string sentence = Console.ReadLine();
            var pigLatin = GetSentenceInPigLatin(sentence);
            Console.WriteLine(pigLatin);
            Console.ReadLine();
        }

        private static string GetSentenceInPigLatin(string sentence)
        {
            const string vowels = "AEIOUaeio";
            var returnSentence = "";
            foreach (var word in sentence.Split())
            {
                var firstLetter = word.Substring(0, 1);
                var restOfWord = word.Substring(1, word.Length - 1);
                var currentLetter = vowels.IndexOf(firstLetter, StringComparison.Ordinal);

                if (currentLetter == -1)
                {
                    returnSentence += restOfWord + firstLetter + "ay ";
                }
                else
                {
                    returnSentence += word + "way ";
                }
            }
            return returnSentence;
        }

答案 2 :(得分:0)

我想出了一个简短的LINQ实现:

string.Join(" ", "testing one translation".Split(' ')
    .Select(word => "aeiouy".Contains(word[0])
            ? word.Skip(1).Concat(word.Take(1))
            : word.ToCharArray())
    .Select(word => word.Concat("way".ToCharArray()))
    .Select(word => string.Concat(word)));

输出:“testingway neoway translationway”

当然,我可能会将其重构为:

"testing one translation"
    .Split(' ')
    .Select(word => word.ToCharsWithStartingVowelLast())
    .Select(word => word.WithEnding("way"))
    .Select(word => string.Concat(word))
    .Join(' ');

static class Extensions {
    public static IEnumerable<char> ToCharsWithStartingVowelLast(this string word)
    {
        return "aeiouy".Contains(word[0])
            ? word.Skip(1).Concat(word.Take(1))
            : word.ToCharArray();
    }
    public static IEnumerable<char> WithEnding(this IEnumerable<char> word, string ending)
    {
        return word.Concat(ending.ToCharArray())
    }
    public static string Join(this IEnumerable<IEnumerable<char>> words, char separator)
    {
        return string.Join(separator, words.Select(word => string.Concat(word)));
    }
}

<强>更新

通过编辑,您询问了辅音群。我喜欢用LINQ执行此操作的一个原因是,更新管道的这一部分非常简单,并使其全部工作:

 public static IEnumerable<char> ToCharsWithStartingConsonantsLast(this string word)
{
    return word.SkipWhile(c => c.IsConsonant()).Concat(word.TakeWhile(c => c.IsConsonant()));
}

public static bool IsConsonant(this char c)
{
    return !"aeiouy".Contains(c);
}

整个管道,没有重构扩展方法,现在看起来像这样:

string.Join(" ", "testing one translation".Split(' ')
    .Select(word => word.SkipWhile(c => !"aeiouy".Contains(c)).Concat(word.TakeWhile(c => !"aeiou".Contains(c))))
    .Select(word => word.Concat("way".ToCharArray()))
    .Select(word => string.Concat(word)))

并输出"estingtway oneway anslationtrway"

更新2:

我注意到我没有正确处理单词结尾。这是一个更新,当单词(没有结尾)以元音结尾时,只需将w添加到结尾:

string.Join(" ", "testing one translation".Split(' ')
    .Select(word => word.SkipWhile(c => !"aeiouy".Contains(c)).Concat(word.TakeWhile(c => !"aeiou".Contains(c))))
    .Select(word =>
    {
        var ending = "aeiouy".Contains(word.Last()) ? "way" : "ay";
        return word.Concat(ending.ToCharArray());
    })
    .Select(word => string.Concat(word)))

输出:"estingtay oneway anslationtray"。请注意它是处理添加更改结尾的步骤 - 算法的所有其他部分都保持不变。

鉴于现在这么简单,我可能只使用两种扩展方法:Join(this IEnumerable<IEnumerable<char>> words, char separator)IsConsonant(this char c)(鉴于上面的代码示例,后者的实现应该很容易)。这产生了以下最终实现:

"testing one translation"
        .Split(' ')
        .Select(word => word.SkipWhile(c => !c.IsVowel()).Concat(word.TakeWhile(c => c.IsVowel())))
        .Select(word => word.Concat((word.Last().IsVowel() ? "way" : "ay").ToCharArray()))
        .Select(word => string.Concat(word))
        .Join(" ")

这里也很容易看到我们要翻译的内容:

  1. 将句子分成单词
  2. 将任何辅音洗到单词的末尾(乍一看,这是不明显的,这是发生的事情,但我找不到更简单的表达方式,除非用扩展方法包装它)
  3. 添加结尾
  4. IEnumerable<char>转换为string s
  5. 将单词重新加入句子