简体   繁体   中英

How can I get all subsets of a set that respect the order

I'm looking for a C# example that will give me all subsets of a set while respecting the order.

For example I have A,B and would like:

A
B
AB
BA

Please note that for my purpose AB != BA .

The solution should be generic for any input type:

List<List<T>> GetSubsets<T>(List<T> originalSet)

I've come across some great solutions using bitwise manipulation for AB == BA (eg Generate all combinations for a list of strings ) but so far I have failed to find anything to solve what I described above.

Any tips/pointers would be much appreciated!

You can do it recursively.

Put the items in a set, and make an empty list containing the items in a subset. Then call your recursive method that populates the list of lists.

On each recursive invocation start by adding the items that you have collected so far to the list of result lists. Then for each item remaining in the set of items do the following:

  1. Remove the item from the remaining set
  2. Add the item to the list containing the partial subset
  3. Make a recursive invocation
  4. Remove the item from the partial subset
  5. Add the item back to the remaining set.

Here is a simple implementation in C#:

static void CollectAll(ISet<String> remaining, IList<string> soFar, List<List<string>> all) {
    if (soFar.Count != 0) {
        all.Add(soFar.ToList());
    }
    foreach (var item in remaining.ToList()) {
        remaining.Remove(item);
        soFar.Add(item);
        CollectAll(remaining, soFar, all);
        soFar.Remove(item);
        remaining.Add(item);
    }
}

Demo.

GetPermutations() is ref. from https://stackoverflow.com/a/10630026/1287352

public static List<List<T>> PermutationOf<T>(HashSet<T> set)
{
    var result = new List<List<T>>();
    for (var length = 1; length <= set.Count; length++)
    {
        result.AddRange(GetPermutations<T>(set, length).Select(i => i.ToList()));
    }
    return result;
}

private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
    if (length == 1) return list.Select(t => new T[] { t });

    return GetPermutations(list, length - 1)
        .SelectMany(t => list.Where(e => !t.Contains(e)),
        (t1, t2) => t1.Concat(new T[] { t2 }));
}

Usage:

PermutationOf(new HashSet<Guid>() { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() })
PermutationOf(new HashSet<String>() { "A", "B", "C" })

Result:

A
B
C
A, B
A, C
B, A
B, C
C, A
C, B
A, B, C
A, C, B
B, A, C
B, C, A
C, A, B
C, B, A

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