1

I am looking at an algorithm that does the following I have two List<String>, say

List<String> A == {"20", "32A", "50K", "50F", "50D", "70", "72"}
List<String> B == {"20", "32A", "72"}

I want to make sure that List B is a subset of A in the proper order.

Examples:

  • B == {"20", "32A", "72"} should return true

  • B == {"20", "32A", "70"} should return true

  • B == {"20", "32A", "40"} should return false (A doesn't have "40")

  • B == {"32A", "20", "70"} should return false (A has "20", "32A", "70" order)

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215

6 Answers6

2
    public static <T> boolean subSetOf(List<T> mainList,
            List<T> candidate) {
        int i = 0;
        for (T v : mainList) {
            if (candidate.get(i).equals(v)) {
                i++;
            }
            if (i >= candidate.size()) {
                return true;
            }
        }
        return false;
    }

Testing with this

        List<String> list = List.of("20", "32A", "50K",
                "50F", "50D", "70", "72");
        List<List<String>> tests = List.of(
                List.of("100"),
                List.of("72"),
                List.of("20", "32A", "72"),
                List.of("20","32","40"),
                List.of("50F", "50D", "70", "72"),
                List.of("32A", "20", "72"),
                List.of("20","32A", "100"),
                list,
                 List.of("20", "32A", "50K",
                            "50F", "50D", "70", "72", "100"));

Prints the following:

false [100]
true [72]
true [20, 32A, 72]
false [20, 32, 40]
true [50F, 50D, 70, 72]
false [32A, 20, 72]
false [20, 32A, 100]
true [20, 32A, 50K, 50F, 50D, 70, 72]
false [20, 32A, 50K, 50F, 50D, 70, 72, 100]

WJS
  • 36,363
  • 4
  • 24
  • 39
2

Let's generalize the problem: if one IEnumerable<T> is ordered subset of another IEnumerable<T> (C#).

Code (C#):

public static bool IsOrderedSubset<T>(IEnumerable<T> list, 
                                      IEnumerable<T> subset, 
                                      IComparer<T> comparer = null) {
  if (null == comparer)
    comparer = Comparer<T>.Default;

  if (null == comparer)
    throw new ArgumentNullException(nameof(comparer), 
                                  $"No default comparer for {typeof(T).Name}");

  if (null == list || null == subset)
    return false;

  using (var enSubset = subset.GetEnumerator()) {
    using (var enList = list.GetEnumerator()) {
      while (enSubset.MoveNext()) {
        while (true) {
          if (!enList.MoveNext())
            return false;
          else if (comparer.Compare(enList.Current, enSubset.Current) == 0)
            break;
        }
      }
    }
  }

  return true;
}

Demo:

List<string> A = new List<String>() {
  "20", "32A", "50K", "50F", "50D", "70", "72"};

List<string>[] Bs = new List<string>[] {
  new List<string>() { "20", "32A", "72"},
  new List<string>() { "20", "32A", "70"},
  new List<string>() { "20", "32A", "40"},
  new List<string>() { "32A", "20", "70"},
};

var report = string.Join(Environment.NewLine, Bs
  .Select(B => $"[{string.Join(", ", B)}] : {(IsOrderedSubset(A, B) ? "true" : "false")}"));

Console.Write(report);

Outcome:

[20, 32A, 72] : true
[20, 32A, 70] : true
[20, 32A, 40] : false
[32A, 20, 70] : false
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
0

code in c sharp

          public static bool IsSub(List<string> a, List<string> b)
            {
                if (a == null && b != null)
                    return false;
                if (a != null && b == null)
                    return true;//your question may require a different return so watch for that(the return is dependent on the purpose of the function)
                if(a==null&&b==null)
                    return true;//your question may require a different return so watch for that(the return is dependent on the purpose of the function)
                int ib = 0;
                for (int ia = 0; ia < a.Count; ia++)
                {
                    if (a[ia] == b[ib])
                        ib++;
                    if (ib == b.Count)
                        return true;
                }
                return false;
            }

test

    List<string> a = new List<String>() {
      "20", "32A", "50K", "50F", "50D", "70", "72"};

    List<string> b = new List<string> {
      "20", "32A", "72"};

    Console.Write(IsSub(a, b));

output: true

Yovel
  • 93
  • 7
0

Here is a method, written in C#, that checks if list A contains a subset with the same order. However, you do not specify if gaps/other items may occur within the order. The method below does not take this into account, but requires the exact subset to occur.

Note that: if a partial/failed match occurs, then the method will recover and continue searching; that is, if you search after B, C, D in List containing A, B, C, B, C, D then it will find the match!

public static bool IsOrderedSubset<T>(IList<T> a, IList<T> b, IEqualityComparer<T> comparer)
{
  //Quick checks
  if (a == null || b == null || b.Count == 0) return false;
  if (ReferenceEquals(a, b)) return true;
  if (b.Count > a.Count) return false;


  for (var aIndex = 0; aIndex < a.Count; aIndex++)
  {
    int bIndex;
    for (bIndex = 0; bIndex < b.Count && aIndex + bIndex < a.Count; bIndex++)
    {
      if (!comparer.Equals(a[aIndex + bIndex], b[bIndex]))
        break; //met a mismatch, so bIndex will be reset, and outer loop continues to find the next, first match.
    }

    if (bIndex == b.Count)
      return true; //Reached end of list b with all matched
  }

  return false;
}
Anders
  • 1,590
  • 1
  • 20
  • 37
0

This code works fine:

public bool IsOrdredSubList(List<string> list, List<string> subList)
        {
            int j = 0;
            int cpt = 0;
            bool found = false;
            for (int i = 0; i < list?.Count; i++)
            {
                if (j < subList?.Count)
                {
                    if (list[i] == subList[j])
                    {
                        j++;
                        found = true;
                    }
                    if (found) cpt++;
                }
            }
            return (cpt == subList?.Count);
        }
ilyes
  • 382
  • 2
  • 10
-2

C# answer can be found in here

public class ListHelper<T>
{
    public static bool ContainsAllItems(List<T> a, List<T> b)
    {
        return !b.Except(a).Any();
    }
}
Sevo
  • 22
  • 5