C# Two lists to one list, LinQ

Markus Freitag 3,786 Reputation points
2020-12-03T09:31:44.777+00:00

Hello,
I have two lists and need a list as result. Is there a way to solve this with LinQ?
If so, how?
44560--onelist.png

My attempts, it would be better maybe to load it into a dictionary, but how?

HashSet<Tuple<string, bool>> hsResultList = new HashSet<Tuple<string, bool>>();  
  
 for (int side = 0; side <= 2; side++)   // Side 1 and Side 2  
 {  
  
 foreach (var sB in CurrentPanel.ListSides[(int)side - 1].Boards )  
 {  
 var qryAlreadyInside = hsResultList.Where(x => x.Item1.Contains(sB.Index)).FirstOrDefault();  
 if ( qryAlreadyInside  == null )  
 hsResultList.Add(new Tuple<string, bool>(sB.Index, sB.Badmark));  

If the status is false in one list, the entire status must be false in the merged dictionary.

var dicSide1 = CurrentPanel.ListSides[0].ListSingleBoards.ToDictionary(x => x.Index, v => v.State);  
var dicSide2 = CurrentPanel.ListSides[1].ListSingleBoards.ToDictionary(x => x.Index, v => v.State);  
var dicResultSide1Side2Badmarks = dicSide1.Union(dicSide2.Where(k => !dicSide1.ContainsKey(k.Key))).ToDictionary(k => k.Key, v => v.Value);  
  
int badBoards = dicResultSide1Side2Badmarks.Where(x => x.Value == false).Count();  
int goodBoards = dicResultSide1Side2Badmarks.Where(x => x.Value == true).Count();  
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,379 questions
0 comments No comments
{count} votes

Accepted answer
  1. Timon Yang-MSFT 9,576 Reputation points
    2020-12-04T02:16:06.74+00:00

    You can also consider this method, merge them, and then group them to determine whether there is false in each group:

            public static void Main()  
            {  
                List<A> list1 = new List<A>() {  
                new A(){ Index = 1, State = false },  
                new A(){ Index = 2, State = false },  
                new A(){ Index = 3, State = true },  
                new A(){ Index = 4, State = false },  
                new A(){ Index = 5, State = false },  
            };  
                List<A> list2 = new List<A>() {  
                new A(){ Index = 1, State = false },  
                new A(){ Index = 2, State = true },  
                new A(){ Index = 3, State = true },  
                new A(){ Index = 4, State = false },  
                new A(){ Index = 5, State = false },  
                new A(){ Index = 6, State = true },  
                new A(){ Index = 7, State = false },  
            };  
                var list = list1.Concat(list2);  
      
                var re = from a in list  
                         group a by a.Index into g  
                         select new  
                         {  
                             Key = g.Key,  
                             Value = g.Where(x => x.State == false).Count() > 0 ? false : true  
                         };  
                Dictionary<int, bool> dict1 = re.ToDictionary(x => x.Key, y => y.Value);  
            }  
    

    45004-1.png


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

4 additional answers

Sort by: Most helpful
  1. Cheong00 3,471 Reputation points
    2020-12-03T11:05:46.867+00:00

    My take on this with LINQ: https://dotnetfiddle.net/RlLMHU

    2 people found this answer helpful.

  2. jjnguy 6 Reputation points
    2020-12-04T02:03:50.14+00:00

    I'd do something like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace scratch
    {
        class Program
        {
            static void Main(string[] args)
            {
                var listOne = new List<bool> { true, false, true, false, true, false, true, true };
                var listTwo = new List<bool> { false, true, true };
                var result = Merge(listOne, listTwo);
            }
    
            static List<bool> Merge(List<bool> one, List<bool> two)
            {
                var longer = one.Count > two.Count ? one : two;
                var shorter = one.Count > two.Count ? two : one;
                return longer
                    .Select((item, ix) => ix >= shorter.Count ? item : item && shorter[ix])
                    .ToList();
            }
        }
    }
    

    The merge method takes in two lists. First it finds the longer of the two, and does a logical AND on the two values or just takes the remaining values.

    I don't think there is much reason to load these into a Dictionary first since you can always get values out of a arrays by index in constant time.

    An extra concise version might look like this:

    static List<bool> Merge2(List<bool> one, List<bool> two)
    {
        return Enumerable.Range(0, Math.Max(one.Count, two.Count))
            .Select(ix =>
                (ix >= one.Count || one[ix])
                &&
                (ix >= two.Count || two[ix]))
            .ToList();
    }
    

    It does the same as above - but is a one-liner.

    1 person found this answer helpful.
    0 comments No comments

  3. Jaliya Udagedara 2,736 Reputation points MVP
    2020-12-03T18:18:08.487+00:00

    May be something simple,

    var list1 = new List<A>()
    {
        new A(){ Index = 1, State = false },
        new A(){ Index = 2, State = false },
        new A(){ Index = 3, State = true },
        new A(){ Index = 4, State = false },
        new A(){ Index = 5, State = false },
    };
    
    var list2 = new List<A>()
    {
        new A(){ Index = 1, State = false },
        new A(){ Index = 2, State = true },
        new A(){ Index = 3, State = false },
        new A(){ Index = 4, State = false },
        new A(){ Index = 5, State = false },
        new A(){ Index = 6, State = true },
        new A(){ Index = 7, State = false },
    };
    
    List<A> leftList = list2;
    List<A> rightList = list1;
    if (list1.Count > list2.Count)
    {
        leftList = list1;
        rightList = list2;
    }
    
    IEnumerable<A> finalList = leftList
        .Select(x =>
        {
            var matchingState = rightList.SingleOrDefault(y => y.Index == x.Index)?.State;
            var finalState = matchingState == null ? x.State : matchingState.Value && x.State;
    
            return new A
            {
                Index = x.Index,
                State = finalState
            };
        });
    

    Output:

    1 False
    2 False
    3 False
    4 False
    5 False
    6 True
    7 False
    
    0 comments No comments

  4. Christopher Bradford 1 Reputation point
    2021-07-13T23:16:22.313+00:00

    Another option:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Newtonsoft.Json;
    
    public class Program
    {
        public static void Main()
        {
            var first = new List<Item>{new Item(1,false), new Item(2, false), new Item(3,true), new Item(4,false), new Item(5,false)};
            var second = new List<Item>{new Item(1,false), new Item(2,true), new Item(3,false), new Item(4,false), new Item(5,false), new Item(6,true), new Item(7,false)};
    
            // Pure LINQ
            var result = second.Zip(first, (firstItem, secondItem) => new Item(firstItem.Index,  firstItem.State && secondItem.State)).Concat(second.Skip(first.Count));
    
            Console.WriteLine(JsonConvert.SerializeObject(result));
        }
    
        private record Item(int Index, bool State);
    }
    
    0 comments No comments