如何使用yield return和recursion获取每个字母组合?
我有几个字符串列表,从几十个可能的列表:
1: { "A", "B", "C" } 2: { "1", "2", "3" } 3: { "D", "E", "F" }
这三个仅作为示例选择,并且用户可以从具有不同数量的元素的数十个类似列表中进行选择。 再举一个例子,这对用户来说也是一个非常有效的选择:
25: { } // empty 4: { "%", "!", "$", "@" } 16: { "I", "a", "b", "Y" } 8: { ")", "z", "!", "8" }
我想要做的是在保持列表的“顺序”的同时获得每个字符串组合。 换句话说,假设我们正在查看第一个列表,第一个组合将是A1D
,然后是A1E
,然后是A1F
,然后是B1D
,然后是B1E
,依此类推。 到目前为止,我已经编写了这个递归算法:
public void Tester() { var 2dList = new List { list1, list2, list3 }; var answer = ReturnString(2dList).ToList(); answer.ForEach(Console.WriteLine); } public IEnumerable ReturnString(List<List> list) { if (!list.Any()) { yield return null; } else { // for each letter in the top-most list... foreach (var letter in list.First()) { // get the remaining lists minus the first one var nextList = list.Where(x => x != list.First()).ToList(); // get the letter and recurse down to find the next yield return letter + ReturnString(nextList); } } }
但是,我得到的回报是:
AStringGeneration.StringGenerator+d__11 BStringGeneration.StringGenerator+d__11 CStringGeneration.StringGenerator+d__11
StringGeneration
是ReturnString
所在类的名称。当我在yield return letter + ...
行上放置一个断点时,它似乎迭代了A
, B
和C
,但实际上并没有递归。 我不确定这里发生了什么。 任何人都可以解释我的算法有什么问题吗?
你需要枚举迭代器:
foreach(string s in ReturnString(...)) { Console.WriteLine(s); }
这也适用于每次迭代:
foreach(string tail in ReturnString(nextList)) yield return letter + tail;
另外,我怀疑你可以在这里用SelectMany做点什么。
from x in l1 from y in l2 from z in l3 select x + y + + z
更新:
这是一个任意版本的大纲。 我稍后会详细说明。
private bool m_beforeStart; private IList> m_lists; private Stack> m_enumerators; public bool MoveNext() { while (CurrentEnumerator != null && !CurrentEnumerator.MoveNext()) { RemoveLastChar(m_stringBuilder); PopEnumerator(); } if (CurrentEnumerator == null && ! m_beforeStart) { return false; } m_beforeStart = false; while (PushEnumerator()) { if (!CurrenEnumerator.MoveNext()) { ClearEnumerators(); return false; } m_stringBuilder.Append( m_currentEnumerator.Current ); } return true; } public string Current { get { return m_stringBuilder.ToString(); } } private IEnumerator CurrentEnumerator { get { return m_enumerators.Count != 0 ? m_enumerators.Peek() : null; } } private void PopEnumerator() { if (m_enumerators.Count != 0) { m_enumerators.Pop(); } } private bool PushEnumerator() { if (m_enumerators.Count == m_lists.Count) { return false; } m_enumerators.Push(m_lists[m_enumerators.Count].GetEnumerator()); }
public static IEnumerable ReturnString(IEnumerable> matrix) { if (matrix.Count() == 1) return matrix.First(); return from letter in matrix.First() // foreach letter in first list let tail = matrix.Skip(1) // get tail lists let tailStrings = ReturnString(tail) // recursively build lists of endings for each tail from ending in tailStrings // foreach string in these tail endings select letter + ending; // append letter from the first list to ending }
调用ReturnString(lst.Where(l => l.Any())
跳过空序列。
上述就是C#学习教程:如何使用yield return和recursion获取每个字母组合?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/951530.html