我有几个像这样的字符串列表,从几十个可能的列表:
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
,然后是{{1 }}, 等等等等。到目前为止,我已经编写了这个递归算法:
B1E
但是,我得到的回报是:
public void Tester()
{
var 2dList = new List { list1, list2, list3 };
var answer = ReturnString(2dList).ToList();
answer.ForEach(Console.WriteLine);
}
public IEnumerable<string> ReturnString(List<List<string>> 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+<ReturnString>d__11
BStringGeneration.StringGenerator+<ReturnString>d__11
CStringGeneration.StringGenerator+<ReturnString>d__11
是StringGeneration
所在类的名称。当我在ReturnString
行上设置断点时,它似乎会遍历yield return letter + ...
,{{ 1}}和A
,但实际上没有递归。我不确定这里发生了什么。任何人都可以解释我的算法有什么问题吗?
答案 0 :(得分:3)
您需要枚举迭代器:
foreach(string s in ReturnString(...)) {
Console.WriteLine(s);
}
这也适用于每次迭代:
foreach(string tail in ReturnString(nextList))
yield return letter + tail;
另外,我怀疑你可以在这里用SelectMany做点什么。
答案 1 :(得分:3)
from x in l1
from y in l2
from z in l3
select x + y + + z
<强>更新强>
这是任意版本的大纲。我稍后会详细说明。
private bool m_beforeStart;
private IList<IEnumerable<char>> m_lists;
private Stack<IEnumerator<char>> 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<char> 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());
}
答案 2 :(得分:1)
public static IEnumerable<string> ReturnString(IEnumerable<IEnumerable<string>> 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())
跳过空序列。