Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将列表转换为带有元音和结尾“and”的字符串_C# - Fatal编程技术网

C# 将列表转换为带有元音和结尾“and”的字符串

C# 将列表转换为带有元音和结尾“and”的字符串,c#,C#,我正试图从列表中创建一个字符串。然而,我希望它被安排在一个有意义的方式,因此,我没有线是苹果,香蕉,爸爸的柑橘,我希望它是我有一个苹果,香蕉,和爸爸的柑橘。。绳子是苹果、香蕉和爸爸的柑橘 我宁愿不改变构成我的列表的字符串;我正在研究的是一个mod,它会根据其他mod的启用情况更改列表,因此在每个组的最后一个字符串中添加“and”不会很好 总之,我想要的代码将列表转换为字符串,在以辅音开头的单词前面添加“a”,在带元音的单词前面添加“an”,在带撇号的单词前面都不添加 谢谢 不清楚您的输入是什么样

我正试图从列表中创建一个字符串。然而,我希望它被安排在一个有意义的方式,因此,我没有线是苹果,香蕉,爸爸的柑橘,我希望它是我有一个苹果,香蕉,和爸爸的柑橘。。绳子是苹果、香蕉和爸爸的柑橘

我宁愿不改变构成我的列表的字符串;我正在研究的是一个mod,它会根据其他mod的启用情况更改列表,因此在每个组的最后一个字符串中添加“and”不会很好

总之,我想要的代码将列表转换为字符串,在以辅音开头的单词前面添加“a”,在带元音的单词前面添加“an”,在带撇号的单词前面都不添加


谢谢

不清楚您的输入是什么样子的,但它可能类似于这个控制台应用程序。然而,英语不是我的第一语言,所以我可能大错特错:

static void Main(string[] args)
{
    List<string> strings = new List<string>
    {
        "apple",
        "banana",
        "Papa's citrus"
    };

    var lastNdx = strings.Count - 1;
    var sentence = "I have " + String.Join(", ", 
        strings.Select((s, ndx) =>
        {
            var ls = s.ToLower();
            string ret = "";
            if ("aeiou".Contains(ls[0]))
                ret = "an " + s;
            else if (ls.Contains("\'"))
                ret = s;
            else ret = "a " + s;
            if (ndx == lastNdx)
                ret = "and " + ret;
            return ret;
        }).ToArray() );

    Console.WriteLine(sentence);
}

使用一些方便的扩展方法:

public static class IEnumerableExt {
    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);
    public static IEnumerable<T> Leave<T>(this ICollection<T> src, int drop) => src.Take(src.Count - drop);
    public static IEnumerable<T> Drop<T>(this ICollection<T> src, int drop) => (drop < 0) ? src.Leave(-drop) : src.Skip(drop);
}

public static class StringExt {
    public static string UpTo(this string s, Regex stopRE) {
        var m = stopRE.Match(s);
        if (m.Success)
            return s.Substring(0, m.Index);
        else
            return s;
    }

    public static string Join(this IEnumerable<string> strings, string sep) => String.Join(sep, strings.ToArray());
    public static bool EndsWithOneOf(this string s, params string[] endings) => endings.Any(e => s.EndsWith(e));
}

Drop和Last在一般情况下并不是特别有效,但因为我们知道我们使用的是列表,所以它们很好,而且不管怎样数据都很短。

这个答案是针对@Stillgar的。这有点复杂,所以我做了第二个答案

下载的最新版本并将其存储在文件夹中。在CMUDictExt类中设置使用该文件夹的路径:

public static class CMUDictExt {
    const string cmuFolder = @"D:\";
    static IEnumerable<string> CMUFiles = Directory.EnumerateFiles(cmuFolder, "cmudict-*");
    static Regex cmudictName = new Regex(@"cmudict-(?:\d+(?:\.\d+)?[a-z]?)+\.?(.*)$", RegexOptions.Compiled);
    static string CMUFile(string ext) => CMUFiles.First(f => cmudictName.Match(f).Groups[1].Value == ext);

    static Dictionary<string, string> phones;
    static Dictionary<string, string[]> pronunciations;
    public static ILookup<string, string> SymbolWords;
    static HashSet<string> exceptions;

    static CMUDictExt() {
        phones = File.ReadLines(CMUFile("phones"))
                     .Select(l => l.Split('\t'))
                     .ToDictionary(pa => pa[0], pa => pa[1]);

        pronunciations = File.ReadLines(CMUFile(""))
                             .Where(l => !l.StartsWith(";;;"))
                             .Where(l => Char.IsLetter(l[0]))
                             .Select(l => l.Split("  ").ToArray())
                             .ToDictionary(wg => wg[0].ToLowerInvariant(), wg => wg[1].Split(' '));

        SymbolWords = pronunciations.SelectMany(wp => wp.Value.Select(s => (Word: wp.Key, s)))
                                    .ToLookup(wp => wp.s, wp => wp.Word);
        exceptions = pronunciations.Where(wp => (wp.Key.StartsWithVowel() ^ wp.Value[0].Phone() == "vowel")).Select(wp => wp.Key).ToHashSet();
    }

    public static string Phone(this string aSymbol) => phones.GetValueOrDefault(aSymbol.UpTo(ch => Char.IsDigit(ch)), String.Empty);

    static string[] emptyStringArray = new string[] {};
    public static string[] Pronunciation(this string aWord) => pronunciations.GetValueOrDefault(aWord.ToLowerInvariant(), emptyStringArray);
    public static bool HasPronunciation(this string aWord) => pronunciations.GetValueOrDefault(aWord.ToLowerInvariant(), null) != null;

    static readonly HashSet<char> vowels = "aeiou".ToHashSet<char>();
    public static bool StartsWithVowel(this string w) => vowels.Contains(w[0]);
    public static bool BeginsWithVowelSound(this string aWord) => exceptions.Contains(aWord) ? !aWord.StartsWithVowel() : aWord.StartsWithVowel(); // guess if not found
}
现在,答案的计算与之前相同,但在默认检查元音之前,它会正确处理许多英语语言异常:

var ans = ("I have " + src.Drop(-1).Select(w => w.ArticleOrPossessive()).Join(", ") + " and " + src.Last().ArticleOrPossessive() + ".");
样本输出:

I have an apple, a banana, Papa's citrus, an honest judge, a highchair, a university and an understanding.

总之,我想要的代码是。。。这对于堆栈溢出来说太宽了。当你无法前进时,你需要自己尝试并提出一个问题,在这里发布代码,这样我们就可以指导你,你已经尝试了什么?@Stilgar我就是这么想的。问题太广泛了,因为OP还没有尝试过任何东西,所以它不是一个代码编写服务。随机尝试正是应该做的。没有人说这个问题质量不高,只是说它不适合这里。@Stillgar所以你认为这个问题表明了研究的努力?@Screerdasnek你仍然可以改进你的问题,这就是我们在这里的最终目标:如果他的字符串中允许使用形容词,那么该方法不正确的单词数量会增加很多。@Stilgar怎么会这样呢?红苹果和橘子一样有效,不是吗?比如诚实vshigh@Stilgar我为你添加了一个答案:现在更像是这样了@Stillgar添加了一些示例输出,并对其进行了一点改进。顺便说一句,我不需要这个,只是好奇什么是合适的解决方案:@Stillgar Me,也是:
public static class IEnumerableExt {
    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);
    public static IEnumerable<T> Leave<T>(this ICollection<T> src, int drop) => src.Take(src.Count - drop);
    public static IEnumerable<T> Drop<T>(this ICollection<T> src, int drop) => (drop < 0) ? src.Leave(-drop) : src.Skip(drop);
    public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> keySelector, Comparer<TKey> keyComparer) => src.Aggregate((a, b) => keyComparer.Compare(keySelector(a), keySelector(b)) < 0 ? a : b);
    public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> keySelector) => src.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keySelector(a), keySelector(b)) < 0 ? a : b);
}

public static class StringExt {
    public static string UpTo(this string s, Regex stopRE) {
        var m = stopRE.Match(s);
        if (m.Success)
            return s.Substring(0, m.Index);
        else
            return s;
    }
    public static string UpTo(this string s, Func<char, bool> testfn) {
        var m = s.Select((ch, Index) => new { ch, Index, Success = testfn(ch) }).FirstOrDefault(cit => cit.Success);
        if (m != null && m.Success)
            return s.Substring(0, m.Index);
        else
            return s;
    }

    public static string Join(this IEnumerable<string> strings, string sep) => String.Join(sep, strings.ToArray());
    public static bool EndsWithOneOf(this string s, params string[] endings) => endings.Any(e => s.EndsWith(e));

    public static IEnumerable<string> Split(this string s, params string[] seps) => s.Split(StringSplitOptions.None, seps);

    public static IEnumerable<string> Split(this string s, StringSplitOptions so, params string[] seps) {
        int pos = 0;
        do {
            var sepPos = seps.Select(sep => new { pos = s.IndexOf(sep, pos) < 0 ? s.Length : s.IndexOf(sep, pos), len = sep.Length }).MinBy(pl => pl.pos);
            if (sepPos.pos > pos || so == StringSplitOptions.None)
                yield return s.Substring(pos, sepPos.pos - pos);
            pos = sepPos.pos + sepPos.len;
        } while (pos <= s.Length);
    }
    public static string FirstWord(this string phrase) => phrase.UpTo(ch => Char.IsWhiteSpace(ch));

    public static bool IsAllLetters(this string s) => s.All(ch => Char.IsLetter(ch)); // faster than Regex
}


public static class DictionaryExt {
    public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV defaultValue) => dict.TryGetValue(key, out TV value) ? value : defaultValue;
}
public static class FruitExt {
    public static bool IsPossessive(this string phrase) => phrase.FirstWord().EndsWithOneOf("'s", "'");

    public static string WithIndefiniteArticle(this string phrase) => (phrase.FirstWord().BeginsWithVowelSound() ? "an " : "a ") + phrase;
    public static string ArticleOrPossessive(this string phrase) => phrase.IsPossessive() ? phrase : phrase.WithIndefiniteArticle();
}
var ans = ("I have " + src.Drop(-1).Select(w => w.ArticleOrPossessive()).Join(", ") + " and " + src.Last().ArticleOrPossessive() + ".");
I have an apple, a banana, Papa's citrus, an honest judge, a highchair, a university and an understanding.