Home > Net >  Find FirstOrDefault based on conditions on a struct list
Find FirstOrDefault based on conditions on a struct list

Time:09-30

enter image description here

I have 2 lists, namely clist with 4 Vector3 values C1, C2, C3, C4 and second list named plist with 4 vector3 values P1, P2, P3, P4. I need to find the minimum distances from the vectors in clist to the vectors in plist. For example, need to find the distance from C1 to P1, P2, P3 and P4. C2 to P1, P2, P3 and P4. C3 to P1, P2, P3, P4. C4 to P1, P2, P3, P4.

For that I have added a struct to store this data like this:

public struct CPDistance
{
    public GameObject p;       
    public GameObject c;       
    public float distance;
    
}

and created a new list of this struct using the code:

public List<CPDistance> tempstruct = new List<CPDistance>();

and I had found the distance between these vectors using the code:

foreach (var ca in clist)
{
    foreach (var pa in plist)
    {
        CPDistance cpd = new CPDistance();
        cpd.p = pa;
        cpd.c= ca;
        cpd.distance = Vector3.Distance(ca.transform.position, pa.transform.position);
        tempstruct.Add(cpd);
    }
}
IEnumerable<CPDistance> query = tempstruct.OrderBy(x => x.distance);
foreach (var item in query)
{
    Debug.Log(item.c.name   "  "   item.p.name   "  "   item.distance);
}

On running the above code I get an output like this:

C4  P1  0.5526165
C2  P3  1.242753
C1  P4  1.519395
C3  P1  1.891354
C2  P4  2.189372
C1  P3  2.390067
C4  P2  4.378077
C3  P2  5.170161
C3  P3  7.519557
C1  P2  7.856441
C3  P4  7.938454
C2  P1  8.108953
C1  P1  8.33768
C2  P2  8.851195
C4  P3  9.264006
C4  P4  9.530743

In the image it can be seen that, C1 is near to P4, C2 is near to P3, C4 is near to P1, and the remaining C3 is near to P2. I need to get the output like this:

C1  P4  1.519395
C2  P3  1.242753
C4  P1  0.5526165
C3  P2  5.170161

I have heard that there is a code named Firstordefault where condition can be given to the variable query to get the above desired output. I have given the code like this:

foreach (var i in clist) 
{
    query.FirstOrDefault(x => x.p == i); 
}

But its not giving the desired output. Can someone help me to find what's the issue with the usage of FirstorDefault code.

CodePudding user response:

If you were merely trying to find the closest point to each item, you could easily do that with LINQ:

var closestToEachP = data.GroupBy(e => e.p)
    .Select(g => g.OrderBy(e => e.distance).First())
    .ToList();

But it looks like you need each point to be removed as an option whenever we find another item close to it. To do that, you'll need to keep track of which items you've found. That would look something like this:

var seenPValues = new HashSet<string>();
var seenCValues = new HashSet<string>();
var closestPairs = new List<CPDistance>();
foreach (var element in data.OrderBy(e => e.distance))
{
    if(!seenPValues.Contains(element.p) && !seenCValues.Contains(element.c))
    {
        seenPValues.Add(element.p);
        seenCValues.Add(element.c);
        closestPairs.Add(element);
    }
}
  • Related