我有一个像这样的字符串列表:
List<string> andOrList = new List<string>();
andOrList.Add("AND");
andOrList.Add("OR");
andOrList.Add("AND");
我有4个列表要合并:
List<int> list1 = new List<int>(new int[] { 19, 23, 29 });
List<int> list2 = new List<int>(new int[] { 1, 4, 29 });
List<int> list3 = new List<int>(new int[] { 1, 5, 23 });
List<int> list4 = new List<int>(new int[] { 2, 4, 19 });
我想使用ANDOr中的AND和OR从这4个列表中创建一个新列表。由于AND的优先级高于OR优先级,因此我将应用AND,因此我将使用这些:
var tempList1 = list1.Intersect(list2).ToList();
var tempList2 = list3.Intersect(list4).ToList();
最后结合这两个临时表,因为有一个OR:
var resulList = tempList1.Union(tempList2);
正如您所看到的,当有定义数量的列表和定义的AND和OR数时,可以手动执行此操作。但是当有n个要组合的列表和n-1个AND和OR数时,我无法以编程方式弄清楚如何进行编程。你能帮帮我吗?感谢。
答案 0 :(得分:4)
我建议将执行分成两个阶段:
1. Performs all `AND`s
2. Perform all `OR`s
E.g。
a & b & c | d | e & f & g | h == // put the right order
(a & b & c) | (d) | (e & f & g) | (h) == // perform ANDs
a_b_c | d | e_f_g | h == // perform ORs
final result
在你的情况下
{19, 23, 29} & {1, 4, 29} | {1, 5, 23} & {2, 4, 19} == // put the right order
({19, 23, 29} & {1, 4, 29}) | ({1, 5, 23} & {2, 4, 19}) == // perform ANDs
{29} | {} == // perform ORs
{29}
实施
private static IEnumerable<T> CombinatorOrAnd<T>(IEnumerable<IEnumerable<T>> sources,
IEnumerable<string> actions) {
List<IEnumerable<T>> orList = new List<IEnumerable<T>>();
// First, do all ANDs
bool isFirst = true;
IEnumerable<T> temp = null;
using (var en = actions.GetEnumerator()) {
foreach (var argument in sources) {
if (isFirst) {
temp = argument;
isFirst = false;
continue;
}
en.MoveNext();
if (en.Current == "AND")
temp = temp.Intersect(argument);
else {
orList.Add(temp);
temp = argument;
}
}
}
orList.Add(temp);
// Finally, perform all ORs
return orList.Aggregate((s, a) => s.Union(a));
}
测试
List<int> list1 = new List<int>(new int[] { 19, 23, 29 });
List<int> list2 = new List<int>(new int[] { 1, 4, 29 });
List<int> list3 = new List<int>(new int[] { 1, 5, 23 });
List<int> list4 = new List<int>(new int[] { 2, 4, 19 });
List<string> andOrList = new List<string>();
andOrList.Add("AND");
andOrList.Add("OR");
andOrList.Add("AND");
var result = CombinatorOrAnd(new List<int>[] { list1, list2, list3, list4}, andOrList);
Console.Write(string.Join(", ", result.OrderBy(item => item)));
结果
29
答案 1 :(得分:1)
对迟来的答案道歉,但我在后台开了这个。这个想法几乎是一样的:首先执行AND
,但是通过改变输入列表的副本来做到这一点。
public static IEnumerable<int> ProcessAndOr(List<string> andOrList, params List<int>[] Input)
{
var lst = new List<IEnumerable<int>>(Input);
for(int i = andOrList.Count -1 ; i >= 0 ; i--)
if(andOrList[i] == "AND")
{
lst[i] = lst[i].Intersect(lst[++i]);
lst.RemoveAt(i--);
}
return lst.SelectMany(l=>l).Distinct();
}
可以使用var resultList = ProcessAndOr(andOrList, list1,list2,list3,list4);
调用该示例并生成29
PS,相反的顺序并不是必需的,但是可以使用单个变量进行迭代。