How to combine lists by priority

I have a list of lines like this:

List<string> andOrList = new List<string>();
andOrList.Add("AND");
andOrList.Add("OR");
andOrList.Add("AND");

And I have 4 lists to combine:

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

I want to create a new list from these 4 lists using ANDs and ORs from andOrList. Since AND has a higher priority than OR, I will use ANDs first, so I will have the following:

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

And finally, combine these two templists, because there is an OR:

var resulList = tempList1.Union(tempList2);

As you can see, this can be done manually when there is a certain number of lists and a certain amount of AND and OR. But I could not figure out how to do this programmatically when there are n list numbers to combine and n-1 numbers AND and OR. Can you help me? Thank.

+4
source share
2

:

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
+4

, . : 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, , , .

+1

Source: https://habr.com/ru/post/1678236/


All Articles