句子的英语到 PigLatin 翻译

English to PigLatin Conversion of a Sentence

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

testing one translation

只会输出:

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

只需在此处放置 += 而不是 =

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 调用中,现在已修复。

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

 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;
        }

我为此想出了一个简短的 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".

更新二:

我注意到我没有正确处理词尾。这是一个更新,当单词(没有结尾)以元音结尾时,只将 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>s 转换为 strings
  5. 将单词重新组合成一个句子