Home > Enterprise >  How to detect overlapping of a value in a list of string exist inside a list C#
How to detect overlapping of a value in a list of string exist inside a list C#

Time:10-19

I have a list of Students, each student can enter one or more addresses. I have to find either any of the addresses overlapped in the list and then retrieve those overlapping objects from the list. below is the example of the list of objects

[
{
  "ID" : 1,
  "Addresses": ["SRJ", "SJ"]
},
{
  "ID" : 2,
  "Addresses": ["SJ"}
},
{
  "ID" : 3,
  "Addresses": ["FRT", "FRI"}
},
{
  "ID" : 4,
  "Addresses": ["NR", "SJ"}
},
]

in the above list SJ is a repeated string in the three of the objects so, I have to return those three objects from the list with ID 1,2,4. I have already done the above using loops but I am looking into the most efficient way of doing this task.

CodePudding user response:

I assume that you have a given address and want to check if that exists somewhere else:

string givenAddress = "SJ";
List<Student> overlappingAddressesStudents = students
    .Where(s => s.Addresses.Contains(givenAddress))
    .ToList();

This might not be more efficient that your loop approach, but maybe it's more readable.

CodePudding user response:

Assuming each list item in your question is mapped to a class like below:

    public class AddressRecord
    {
        public int ID { get; set; }
        public List<string> Addresses { get; set; }
    }

You can then use a Linq expression like below to find duplicates and construct an object that tracks all duplicate addresses and IDs those addresses belong to:

var result = list.SelectMany(x => x.Addresses).GroupBy(x => x).Where(x => x.Count() > 1)
.Select(x => new { x.Key, IDs = list.Where(y => y.Addresses.Contains(x.Key)).Select(y => y.ID).ToList() })
.ToList()

First line in linq expression flattens the address list, runs a groupby expression on them and finds all addresses that exist more than once (across all "addresses" lists.)

Then the second line select each address with duplicates and IDs corresponding to that address. (Note that x in x.Key is the IGrouping object created by the groupby expression and x.Key is the address that the grouping was created on.)

The result object should look something like this when serialized:

[{"Key":"SJ","IDs":[1,2,4]}]

Runtime performance wise, a handmade for loop would most certainly beat this expression. However, from maintainability perspective, this linq expression is likely much easier to manage. (This does depend on comfort level of team with linq.)

  • Related