简体   繁体   中英

Compare two Lists using Linq for partial matches

I tried looking through some of the other questions, but couldn't find any that did a partial match.

I have two List<string>

They have codes in them. One is a list of selected codes, one is a list of required codes. The entire code list is a tree though, so they have sub codes. An example would be Code B Code B.1 Code B.11

So lets say the Required code is B, but anything under it's tree will meet that requirement, so if the Selected codes are A and C the match would fail, but if one of the selected codes was B.1 it contains the partial match.

I just need to know if any of the selected codes partially match any of the required codes. Here is my current attempt at this.

//Required is List<string> and Selected is a List<string>
int count = (from c in Selected where c.Contains(Required.Any()) select c).Count();

The error I get is on the Required.Any() and it's cannot convert from bool to string.

Sorry if this is confusing, let me know if adding any additional information would help.

I think you need something like this:

using System;
using System.Collections.Generic;
using System.Linq;

static class Program {
    static void Main(string[] args) {
        List<string> selected = new List<string> { "A", "B", "B.1", "B.11", "C" };
        List<string> required = new List<string> { "B", "C" };
        var matching = from s in selected where required.Any(r => s.StartsWith(r)) select s;
        foreach (string m in matching) {
            Console.WriteLine(m);
        }
    }
}

Applying the Any condition on required in this way should give you the elements that match - I'm not sure if you should use StartsWith or Contains , that depends on your requirements.

If selected and required lists are large enough the following is faster than the accepted answer:

static void Main(string[] args)
{
    List<string> selected = new List<string> { "A", "B", "B.1", "B.11", "C" };
    List<string> required = new List<string> { "B", "C" };
    required.Sort();
    var matching = selected.Where(s =>
    {
        int index = required.BinarySearch(s);
        if (index >= 0) return true; //exact match
        index = ~index;
        if (index == 0) return false;
        return s.StartsWith(required[index - 1]);
    });
    foreach (string m in matching)
    {
        Console.WriteLine(m);
    }
}

Given n = required.Count and m = required.Count the accepted answer algorithm complexity is O(n*m) . However what I propose has a better algorithm complexity: O((n+m)*Log(n))

This query finds any match that exists in two lists. If a value exists in both lists, it returns true , otherwise false .

List<string> listString1 = new List<string>();
List<string> listString2 = new List<string>();

listString1.Add("A");
listString1.Add("B");
listString1.Add("C");
listString1.Add("D");
listString1.Add("E");

listString2.Add("C");
listString2.Add("X");
listString2.Add("Y");
listString2.Add("Z");

bool isItemExist = listString1.Any(x => listString2.Contains(x));

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