简体   繁体   中英

Find overlapping between two lists in c#

I have got a matlab code which calculates the overlap of two lists. In fact it check if a list H is inside another list U and keeps the window of list U where the list H is inside(at least one time). In fact U, H is index list of Nx2 size where in every point there two values for the begining index of the window and the end index of the window. My code in matlab is:

function W = getwindowsspecial(U,H)
W = [];
for i = 1:size(U,1)
  if any(H(:,1)>=U(i,1) & H(:,1)<=U(i,2))
    W = [W;U(i,:)];
  end
end

For example U could be:

54  86
112 217
292 325
402 451
628 664

H could be:

129 214
297 321
406 447
637 664

and the result W is:

112 217
292 325
402 451

I want to convert that code to c#. My list U, H are as List>>. My correspondant function is the following:

 static List<int> getWindows(List<List<int>> list1, List<List<int>> list2)
    {
        List<int> list3 = new List<int>();

        for (int index = 0; index < list1[0].Count; index++) { 

        }

            return list3;
    }

What should I fill in my function in order to work as the Matlab one?

EDIT: In this code I add the limits for the first and the second list. How is it possible to add those limits to Tuple instead of list of lists?

        List<List<int>> first = new List<List<int>>();
        List<List<int>> second = new List<List<int>>();
        first.Add(upFirst); first.Add(downFirst);
        second.Add(upSecond); second.Add(downSecond);

        getWindows(first, second);

upFirst and upSecond contains all the left limits for the first and second list and downFirst and downSecond contains all the right limits for the first and the second lists. I tried to use the following code to do my job:

 for (int index = 0; index < upFirst.Count; index++){

            first.Add(new List<int> { upFirst[index], downFirst[index] });

 }

 for (int index = 0; index < upSecond.Count; index++){

           second.Add(new List<int> { upSecond[index], downSecond[index]});

  }
  List<List<int>> lista = GetWindows(first, second);

This is what I tried in order to add as tuples. However using as the function of @M. Nasser Javaid I got NULL as result. The input that I provide the list of lists first and second are: 在此处输入图片说明

You could do this with a few LINQ queries against the two lists. To make it read a little easier, I'll assume you have lists of tuples, ie List<Tuple<int, int>> s, rather than lists of lists.

var W = U.Where(u => H.Any(h => h.Item1 >= u.Item1 && h.Item1 <= u.Item2));

Note that this replicates the logic in your MATLAB sample, but doesn't give the results you specify in your sample. If you want to replicate the sample, change the second condition to h.Item2 < u.Item2 , ie look at the end of the element from H, and require strict inequality.


Tuple s vs List s

If the Tuple<int,int> s feel strange, don't worry - they're really easy to construct:

var t = Tuple.Create(2, 3);

Depending on where you get your data from, this shouldn't be troublesome. If, however, you already have your data as List<List<int>> s, you can easily change the condition to use h[0] instead of h.Item1 etc.

The main reason I suggest tuples is that they're going to be much more efficient, especially if you have many rows in your matrices U and H .

Try this please. According to given scenario we need numbers from U which are in the range of H so they are...

public void Test()
    {
        var listU = new List<List<int>>
        {
            new List<int> {54, 86},
            new List<int> {112, 217},
            new List<int> {292, 325},
            new List<int> {402, 451},
            new List<int> {628, 664}
        };
        var listH = new List<List<int>>
        {
            new List<int> {129, 214},
            new List<int> {297, 321},
            new List<int> {406, 447},
            new List<int> {637, 664}
        };
        GetWindows(listU, listH);
    }

static List<List<int>> GetWindows(List<List<int>> listU, List<List<int>> listH)
    {
        List<List<int>> list3 = new List<List<int>>();
        var startingOfH = listH.First()[0];
        var endOfH = listH.Last()[listH.Last().Count - 1];
        foreach (var num in listU)
        {
            var initial = num[0];
            var final = num[num.Count - 1];
            if (initial > startingOfH && final < endOfH)
            {
                list3.Add(num);
            }
        }
        return list3;
    }

Edit: If you want to use as Linq then use this

static List<List<int>> GetWindows(List<List<int>> listU, List<List<int>> listH)
    {
        var startingOfH = listH.First()[0];
        var endOfH = listH.Last()[listH.Last().Count - 1];
        return (from num in listU 
                let initial = num[0] 
                let final = num[num.Count - 1] 
                where initial > startingOfH && final < endOfH 
                select num).ToList();
    }

Edit 2: Ignore initial value

static List<List<int>> GetWindows(List<List<int>> listU, List<List<int>> listH)
    {
        List<List<int>> list3 = new List<List<int>>();
        var startingOfH = listH.First()[0];
        var endOfH = listH.Last()[listH.Last().Count - 1];
        foreach (var num in listH)
        {
            var final = num[num.Count - 1];
            if (final > startingOfH && final < endOfH)
            {
                list3.Add(num);
            }
        }
        return list3;
    }

If you like Linq then

static List<List<int>> GetWindows(List<List<int>> listU, List<List<int>> listH)
    {
        var startingOfH = listH.First()[0];
        var endOfH = listH.Last()[listH.Last().Count - 1];
        return (from num in listH 
                let final = num[num.Count - 1] 
                where final > startingOfH && final < endOfH 
                select num).ToList();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM