Creating a list of an object which either does or doesn't exist in another different object list - C#

278 views Asked by At

So I am trying to compare two different lists that both contain differently structured objects. One is easily accessible while the other is very nested in arrays, but sadly, these are responses from API calls so it's not a structure I can change to make them easier to compare. I want to have a list of the complete structures of items found:

var foundList = new List<Structure1>();
var notFoundList = new List<Structure1>(); 

The way the objects are structured are as follows:

public class ObjectsA
{
    public Structure1[] Structure1 {get; set;}
}

public class Structure1
{
    public int id {get; set;} //1
}

And the other object looks like:

public class ObjectsB
{
    public Array1[] array1{get; set}
}

public class Array1
{
    public Array2[] array2{get; set;}
}

public class Array2
{
    public string id {get; set;} //"0001"
}

In a list, I added all the objects that came back from the API call, so ObjectAList contains technically just 1 deserialized object response, which contains an array of objects, while ObjectBList contains a list of objects added to it via AddRange.

At first I tried to putting an Array.Exists() inside of 2 foreach() statements.

foreach (var arr1 in ObjectsBList){ 
  foreach (var arr2 in a.Array2){ 
    if (Array.Exists(ObjectAList.Structure1, item => item.id == Convert.ToInt32(arr2.id)) == true){
      foundList.AddRange(ObjectAList.Structure1);
    }
    else{
      notFoundList.AddRange(ObjectAList.Structure1)
    }}};

This code seemed to keep looping on the "item => item.id == Convert.ToInt32(arr2.id)" part of it, so consequently, it kept going till it found its match and so the answer was always 'true', therefore just putting everything in the foundList. I know I'm probably going at this wrong. I'm just starting out C# programming and I'm having trouble wrapping my mind around some of these things and knowing what all functions exists to help with what I need, etc. Any help would be great!

2

There are 2 answers

0
Arvis On BEST ANSWER
    var objA = new ObjectsA();
    var objB = new ObjectsB();

    var objAIds = objA.Structure1.Select(x => x.Id).Distinct();
    var objBIds = objB.Array1.SelectMany(x => x.Array2).Select(x => int.Parse(x.Id)).Distinct();

    var foundInBothList = objAIds.Intersect(objBIds);
    var notFoundinBList = objAIds.Except(objBIds);

    var inBoth = objA.Structure1.Where(x => foundInBothList.Contains(x.Id));
    var notInB = objA.Structure1.Where(x => notFoundinBList.Contains(x.Id));

Starting from .NET 6

    var objBIds = objB.Array1.SelectMany(x => x.Array2).Select(x => int.Parse(x.Id)).Distinct();
    var foundList = objA.Structure1.IntersectBy(objBIds, x => x.Id);
    var notFoundList = objA.Structure1.ExceptBy(objBIds, x => x.Id);
0
Nitin Sawant On

You can use linq for querying the in-memory objects.

pseudo code

public class Test {
    public void T()
    {
        var ObjectsBList = new ObjectsB();
        var ObjectAList = new ObjectsA();
        var foundList = new List<Structure1>();
        var notFoundList = new List<Structure1>();

        var bList = ObjectsBList
            .array1
            .SelectMany(x => x.array2)
            .Select(x => Convert.ToInt32(x.id))
            .Distinct()
            .ToList();

        if (ObjectAList.Structure1.Any(x => bList.Contains(x.id)))
        {
            foundList.AddRange(ObjectAList.Structure1);
        }
        else
        {
            notFoundList.AddRange(ObjectAList.Structure1);
        }
    }
}

More simplified version:
Introduce an ID list property

using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;



public class ObjectsA
{
    public Structure1[] Structure1 { get; set; }

    public List<int> IDs
    {
        get
        {
            return Structure1.Select(x => x.id).Distinct().ToList();
        }
    }
}

public class Structure1
{
    public int id { get; set; } //1
}

public class ObjectsB
{
    public Array1[] array1 { get; set; }

    public List<int> IDs
    {
        get
        {
            return array1
                .SelectMany(x => x.array2)
                .Select(x => Convert.ToInt32(x.id))
                .Distinct()
                .ToList();
        }
    }
}

public class Array1
{
    public Array2[] array2 { get; set; }
}

public class Array2
{
    public string id { get; set; } //"0001"
}

public class Test
{
    public void T()
    {
        var ObjectsBList = new ObjectsB();
        var ObjectAList = new ObjectsA();
        var foundList = new List<Structure1>();
        var notFoundList = new List<Structure1>();

        if (ObjectAList.IDs.Any(x => ObjectsBList.IDs.Contains(x)))
        {
            foundList.AddRange(ObjectAList.Structure1);
        }
        else
        {
            notFoundList.AddRange(ObjectAList.Structure1);
        }
    }
}