-2

Given a list of pairs such as

        List<int> pair1 = new List<int>() { 1, 3};
        List<int> pair2 = new List<int>() { 1, 2 };
        List<int> pair3 = new List<int>() { 5, 3 };
        List<int> pair4 = new List<int>() { 7, 8 };
        List<int> pair5 = new List<int>() { 8, 11 };
        List<int> pair6 = new List<int>() { 6, 9 };
        List<int> pair7 = new List<int>() { 2, 13 };
        List<int> pair8 = new List<int>() { 13, 16 };

How can I find all of the unions where the pairs intersect?

Output should be something like the following:

1,2,3,5,13,16
7,8,11
6,9


// create lists of pairs to sort through
static void links2XML(SQLiteConnection m_dbConnection)
{
    List<int> pair1 = new List<int>() { 1, 3};
    List<int> pair2 = new List<int>() { 1, 2 };
    List<int> pair3 = new List<int>() { 5, 3 };
    List<int> pair4 = new List<int>() { 7, 8 };
    List<int> pair5 = new List<int>() { 8, 11 };
    List<int> pair6 = new List<int>() { 6, 9 };
    List<int> pair7 = new List<int>() { 2, 13 };
    List<int> pair8 = new List<int>() { 13, 16 };
    var pairs = new List<List<int>>();

    pairs.Add(pair1);
    pairs.Add(pair2);
    pairs.Add(pair3);
    pairs.Add(pair4);
    pairs.Add(pair5);
    pairs.Add(pair6);
    pairs.Add(pair7);
    pairs.Add(pair8);

    var output = new List<int>();
    foreach (var pair in pairs)
    {
        foreach (int i in followLinks(pair, pairs))
        {
            Console.Write(i + ",");
        }
        Console.WriteLine();
    }
}

// loop through pairs to find intersections and recursively call function to 
//build full list of all such ints

static List<int> followLinks(List<int> listA, List<List<int>> listB)
{
    var links = listA;
    var listC = listB.ToList();

    bool added = false;
    foreach (var l in listB)
    {
        var result = listA.Intersect(l);
        if (result.Count<int>() > 0)
        {
            links = links.Union<int>(l).ToList();
            listC.Remove(l); // remove pair for recursion after adding
            added = true;
        }
    }
    if (added)
    {
        followLinks(links, listC);  //recursively call function with updated 
    //list of pairs and truncated list of lists of pairs
        return links;
    }
    else return links;
}

Code should query the lists of pairs and output groups. I've tried this a few different ways, and this seems to have gotten the closest. I'm sure it requires a recursive loop, but figuring out the structure of it is just not making sense to me at the moment.

To clarify for some of the questions the number pairs are random that I chose for this question. The actual data set will be far larger and pulled from a database. That part is irrelevant to my question, though, and it's already solved anyway. It's really just this sorting that is giving me trouble.

To further clarify, the output will find a list of all of the integers from each pair that had an intersection... given pairs 1,2 and 1,3 the output would be 1,2,3. Given pairs 1,2 and 3,5, the output would be 1,2 for one list and 3,5 for the other. Hopefully that makes it clearer what I'm trying to find.

D Sonnier
  • 1
  • 2
  • Use a HashSet and use UnionWith and/or IntersectWith https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx – Rafael Jan 22 '18 at 14:09
  • I guess you'll need to explain a little better: What does "intersect" mean for those tuples? Please show the _logic_ why this is your expected result. You only show 8 pairs, but your result contains numbers up to `16`.... – René Vogt Jan 22 '18 at 14:10
  • Hi! Please add the code you have used to try and solve the problem rather than asking for stackoverflow to solve the problem for you. – Sam Jan 22 '18 at 14:16
  • I've updated with more explanation and sample code. Also, Mr. Vogt, I've begun reading up on your hash set suggestion. – D Sonnier Jan 22 '18 at 15:05
  • Sven, your suggestion led me to the solution. I built a recursive function that scans the list of number pairs back and forth until all linked pairs are found and added to a hash set. I loop through the entire list of pairs and call that function each time and output those to a list of number hash sets filtering it to not include duplicate hashes. It was deceptively simple once I figured out how the hash set class worked. Thank you very much. – D Sonnier Jan 23 '18 at 13:25

1 Answers1

0

I used this function to return the full hash set of all links then loop through all of the initial pairs to feed this function. I filter the results to remove duplicates, and it solves the issue. Suggestion was from user Sven.

// Follow links to build hashset of all linked tags
    static HashSet<int> followLinks(HashSet<int> testHs, List<HashSet<int>> pairs)
    {
        while (true)
        {
            var tester = new HashSet<int>(testHs);
            bool keepGoing = false;
            foreach (var p in pairs)
            {
                if (testHs.Overlaps(p))
                {
                    testHs.UnionWith(p);
                    keepGoing = true;
                }
            }
            for (int i = pairs.Count - 1; i == 0; i-- )
            {
                if (testHs.Overlaps(pairs[i]))
                {
                    testHs.UnionWith(pairs[i]);
                    keepGoing = true;
                }
            }
                if (!keepGoing) break;
            if (testHs.SetEquals(tester)) break;
        }
        return testHs;
    }
D Sonnier
  • 1
  • 2