NSFastListCompare.psm1

$id = get-random

#region C# FastListCompare Class Definition
Add-Type -TypeDefinition @"
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
 
public class NSFastListCompare$id {
    public string[] list1 { get; set; }
    public string[] list2 { get; set; }
 
    // Represents a node in the Trie
    public class TrieNode
    {
        public ConcurrentDictionary<char, TrieNode> Children = new ConcurrentDictionary<char, TrieNode>();
        public bool EndOfWord;
    }
 
    // Implements the Trie data structure
    public class Trie
    {
        private TrieNode root;
 
        public Trie()
        {
            root = new TrieNode();
        }
 
        // Insert a word into the Trie
        public void Insert(string word)
        {
            TrieNode node = root;
            foreach (char c in word)
            {
                node = node.Children.GetOrAdd(c, new TrieNode());
            }
            node.EndOfWord = true;
        }
 
        // Insert all suffixes of the word into the Trie
        public void InsertAllSuffixes(string word)
        {
            for (int i = 0; i < word.Length; i++)
            {
                Insert(word.Substring(i));
            }
        }
 
        // Search if the Trie contains the given word as a substring
        public bool ContainsSubstring(string word)
        {
            TrieNode node = root;
            foreach (char c in word)
            {
                if (node.Children.TryGetValue(c, out TrieNode nextNode))
                {
                    node = nextNode;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
    }
 
    // Function for exact matching
    public List<string> InBothLists(bool caseSensitive)
    {
        HashSet<string> set1, set2;
        if (caseSensitive)
        {
            set1 = new HashSet<string>(list1);
            set2 = new HashSet<string>(list2);
        }
        else
        {
            set1 = new HashSet<string>(list1, StringComparer.OrdinalIgnoreCase);
            set2 = new HashSet<string>(list2, StringComparer.OrdinalIgnoreCase);
        }
 
        set1.IntersectWith(set2); // Intersection of both sets
        return new List<string>(set1);
    }
 
    // Function to return elements from list1 but not in list2
    public List<string> InList1ButNotList2(bool caseSensitive)
    {
        HashSet<string> set1, set2;
        if (caseSensitive)
        {
            set1 = new HashSet<string>(list1);
            set2 = new HashSet<string>(list2);
        }
        else
        {
            set1 = new HashSet<string>(list1, StringComparer.OrdinalIgnoreCase);
            set2 = new HashSet<string>(list2, StringComparer.OrdinalIgnoreCase);
        }
 
        set1.ExceptWith(set2); // Difference
        return new List<string>(set1);
    }
 
    // Function to return elements from list2 but not in list1
    public List<string> InList2ButNotList1(bool caseSensitive)
    {
        HashSet<string> set1, set2;
        if (caseSensitive)
        {
            set1 = new HashSet<string>(list1);
            set2 = new HashSet<string>(list2);
        }
        else
        {
            set1 = new HashSet<string>(list1, StringComparer.OrdinalIgnoreCase);
            set2 = new HashSet<string>(list2, StringComparer.OrdinalIgnoreCase);
        }
 
        set2.ExceptWith(set1); // Difference
        return new List<string>(set2);
    }
 
    // Function to check if list2 substrings are in list1 using the optimized Trie approach
    public List<string> List1SubStringInList2(bool caseSensitive)
    {
        Trie trie = new Trie();
 
        // Insert all suffixes of all words in list2 into the Trie
        Parallel.ForEach(list2, item2 =>
        {
            string itemToInsert = caseSensitive ? item2 : item2.ToLower();
            trie.InsertAllSuffixes(itemToInsert);
        });
 
        List<string> matches = new List<string>();
 
        // Check if any word in list1 is a substring of any word in list2 using the Trie
        Parallel.ForEach(list1, item1 =>
        {
            string itemToCheck = caseSensitive ? item1 : item1.ToLower();
            if (trie.ContainsSubstring(itemToCheck))
            {
                lock (matches)
                {
                    matches.Add(item1);
                }
            }
        });
 
        return matches;
    }
 
    // Function to check if list1 substrings are in list2 using the optimized Trie approach
    public List<string> List2SubStringInList1(bool caseSensitive)
    {
        Trie trie = new Trie();
 
        // Insert all suffixes of all words in list1 into the Trie
        Parallel.ForEach(list1, item1 =>
        {
            string itemToInsert = caseSensitive ? item1 : item1.ToLower();
            trie.InsertAllSuffixes(itemToInsert);
        });
 
        List<string> matches = new List<string>();
 
        // Check if any word in list2 is a substring of any word in list1 using the Trie
        Parallel.ForEach(list2, item2 =>
        {
            string itemToCheck = caseSensitive ? item2 : item2.ToLower();
            if (trie.ContainsSubstring(itemToCheck))
            {
                lock (matches)
                {
                    matches.Add(item2);
                }
            }
        });
 
        return matches;
    }
}
"@

#endregion


<#
.SYNOPSIS
Finds elements present in both lists.
 
.DESCRIPTION
This function compares two lists and returns the elements that are present in both lists. It can perform case-sensitive or case-insensitive comparisons.
 
.PARAMETER list1
The first list to compare.
 
.PARAMETER list2
The second list to compare.
 
.PARAMETER caseSensitive
Boolean flag to indicate if the comparison should be case-sensitive.
 
.EXAMPLE
$commonItems = Compare-InBothLists -list1 $list1 -list2 $list2 -caseSensitive $false
#>

function Compare-InBothLists {
    param (
        [Parameter(Mandatory=$true)]
        [array]$list1,
        
        [Parameter(Mandatory=$true)]
        [array]$list2,

        [bool]$caseSensitive = $false
    )

    $Compare = New-Object NSFastListCompare$id
    $Compare.list1 = $list1
    $Compare.list2 = $list2
    $CompareReturn = @()
    $CompareReturn = $Compare.InBothLists($caseSensitive)
    
    return $CompareReturn
}

<#
.SYNOPSIS
Finds elements present in list1 but not in list2.
 
.DESCRIPTION
This function compares two lists and returns the elements that are present in list1 but not in list2. It can perform case-sensitive or case-insensitive comparisons.
 
.PARAMETER list1
The first list to compare.
 
.PARAMETER list2
The second list to compare.
 
.PARAMETER caseSensitive
Boolean flag to indicate if the comparison should be case-sensitive.
 
.EXAMPLE
$uniqueItems = Compare-InList1ButNotList2 -list1 $list1 -list2 $list2 -caseSensitive $false
#>

function Compare-InList1ButNotList2 {
    param (
        [Parameter(Mandatory=$true)]
        [array]$list1,
        
        [Parameter(Mandatory=$true)]
        [array]$list2,

        [bool]$caseSensitive = $false
    )

    $Compare = New-Object NSFastListCompare$id
    $Compare.list1 = $list1
    $Compare.list2 = $list2
    $CompareReturn = @()
    $CompareReturn = $Compare.InList1ButNotList2($caseSensitive)
    
    return $CompareReturn
}

<#
.SYNOPSIS
Finds elements present in list2 but not in list1.
 
.DESCRIPTION
This function compares two lists and returns the elements that are present in list2 but not in list1. It can perform case-sensitive or case-insensitive comparisons.
 
.PARAMETER list1
The first list to compare.
 
.PARAMETER list2
The second list to compare.
 
.PARAMETER caseSensitive
Boolean flag to indicate if the comparison should be case-sensitive.
 
.EXAMPLE
$uniqueItems = Compare-InList2ButNotList1 -list1 $list1 -list2 $list2 -caseSensitive $false
#>

function Compare-InList2ButNotList1 {
    param (
        [Parameter(Mandatory=$true)]
        [array]$list1,
        
        [Parameter(Mandatory=$true)]
        [array]$list2,

        [bool]$caseSensitive = $false
    )

    $Compare = New-Object NSFastListCompare$id
    $Compare.list1 = $list1
    $Compare.list2 = $list2
    $CompareReturn = @()
    $CompareReturn = $Compare.InList2ButNotList1($caseSensitive)
    
    return $CompareReturn
}

<#
.SYNOPSIS
Finds elements in list1 that are substrings of elements in list2.
 
.DESCRIPTION
This function compares two lists and returns the elements in list1 that are substrings of any element in list2. It uses a Trie data structure for optimized substring search and can perform case-sensitive or case-insensitive comparisons.
 
.PARAMETER list1
The first list to compare.
 
.PARAMETER list2
The second list to compare.
 
.PARAMETER caseSensitive
Boolean flag to indicate if the comparison should be case-sensitive.
 
.EXAMPLE
$substringMatches = Compare-List1SubStringInList2 -list1 $list1 -list2 $list2 -caseSensitive $false
#>

function Compare-List1SubStringInList2 {
    param (
        [Parameter(Mandatory=$true)]
        [array]$list1,
        
        [Parameter(Mandatory=$true)]
        [array]$list2,

        [bool]$caseSensitive = $false
    )

    $Compare = New-Object NSFastListCompare$id
    $Compare.list1 = $list1
    $Compare.list2 = $list2
    $CompareReturn = @()
    $CompareReturn = $Compare.List1SubStringInList2($caseSensitive)
    
    return $CompareReturn
}

<#
.SYNOPSIS
Finds elements in list2 that are substrings of elements in list1.
 
.DESCRIPTION
This function compares two lists and returns the elements in list2 that are substrings of any element in list1. It uses a Trie data structure for optimized substring search and can perform case-sensitive or case-insensitive comparisons.
 
.PARAMETER list1
The first list to compare.
 
.PARAMETER list2
The second list to compare.
 
.PARAMETER caseSensitive
Boolean flag to indicate if the comparison should be case-sensitive.
 
.EXAMPLE
$substringMatches = Compare-List2SubStringInList1 -list1 $list1 -list2 $list2 -caseSensitive $false
#>

function Compare-List2SubStringInList1 {
    param (
        [Parameter(Mandatory=$true)]
        [array]$list1,
        
        [Parameter(Mandatory=$true)]
        [array]$list2,

        [bool]$caseSensitive = $false
    )

    $Compare = New-Object NSFastListCompare$id
    $Compare.list1 = $list1
    $Compare.list2 = $list2
    $CompareReturn = @()
    $CompareReturn = $Compare.List2SubStringInList1($caseSensitive)
    
    return $CompareReturn
}