2017-05-31 50 views
4

我有一個字符串像這樣的列表:如何列出關於相結合,優先

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

我想打從一個新的列表這4個列表使用來自andOrList的AND和OR。由於AND的優先級高於OR第一我會申請與運算所以我有這些:

var tempList1 = list1.Intersect(list2).ToList(); 
    var tempList2 = list3.Intersect(list4).ToList(); 

最後結合這兩種templists因爲有一個OR:

var resulList = tempList1.Union(tempList2); 

正如你可以看到它的可能當有定義數量的列表和已定義的AND和OR的數量時,可以手動完成此操作。但是我不知道如何以編程的方式做到這一點,當有n個列表組合和n-1個AND和OR時。你能幫助我嗎?謝謝。

+0

我認爲你將不得不編寫一種運算符優先級解析器。 – aloisdg

+0

@aloisdg逆向波浪符號的不同版本? – jason

+0

你可以依賴RPN,但它不是必須的 – aloisdg

回答

4

我建議拆分成執行階段:

1. Performs all `AND`s 
2. Perform all `OR`s 

例如

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

道歉爲遲來的答案,但我有這在後臺打開。這個想法幾乎是一樣的:首先執行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,相反的順序是不是真的有必要,但做是爲了能夠使用單個變量進行迭代。