Reputation: 761
I'm stuck with a combination problem.
What I got is a Data
class which basically holds a name
and a list of values
:
public abstract class DataField : IDataField
{
public string Name { get; set; }
public List<string> Values { get; set; }
}
At runtime what I'm trying to do is to get every possible combination of a List<DataField>
object. What i tried so far is:
// Get dataFields with values
List<IDataField> propertyDataFields = mDataFields.Where(x => x.Values.Count > 0).ToList();
var props = GetPropertiesList(propertyDataFields, 0, propertyDataFields.Count - 1, new List<List<FieldProperties>>());
private static List<List<FieldProperties>> GetPropertiesList(List<IDataField> propertyDataFields, int listPosition, int position, List<List<FieldProperties>> fieldPropertiesList)
{
var fieldProperties = new List<FieldProperties>();
foreach (var item in propertyDataFields[position].Values)
{
if (position == -1)
{
GetPropertiesList(propertyDataFields, listPosition + 1, propertyDataFields.Count - 1, fieldPropertiesList);
}
fieldProperties.Add(new FieldProperties(propertyDataFields[position].Name, item));
GetProperties(propertyDataFields, position - 1, fieldProperties, fieldPropertiesList);
}
return fieldPropertiesList;
}
private static void GetProperties(List<IDataField> propertyDataFields, int position, List<FieldProperties> fieldProperties, List<List<FieldProperties>> fieldPropertiesList)
{
if (position == -1)
{
fieldPropertiesList.Add(fieldProperties);
}
foreach (var item in propertyDataFields[position].Values)
{
fieldProperties.Add(new FieldProperties(propertyDataFields[position].Name, item));
GetProperties(propertyDataFields, position - 1, fieldProperties, fieldPropertiesList);
}
}
At the end i need a List of Lists of FieldProperties
objects. The idea was to start with the last dataField
in list and loop through all other using a foreach
everytime, but this won't work if the first list got only 1
entry for example. Maybe sorting by Values
. Count
is an idea?
Edit: FieldProperties
is a class from another dll im using. I need to create an instance for every DataField.Value.
The szenario is: I got a List<IDataField>
e.g.
var dataFieldAuthor = new DataField() {
Name = "Author"
Values = new List<string> { "Author1", "Author2", "Author3" };
}
and i want to create a List<List<FieldProperties>>
with all possible combinations of DataField values.
Upvotes: 0
Views: 231
Reputation: 205539
You can use the generic method from my answer to How to iterate lists with different lengths to find all permutations?:
public static class Algorithms
{
public static IEnumerable<T[]> GenerateCombinations<T>(this IReadOnlyList<IReadOnlyList<T>> input)
{
var result = new T[input.Count];
var indices = new int[input.Count];
for (int pos = 0, index = 0; ;)
{
for (; pos < result.Length; pos++, index = 0)
{
indices[pos] = index;
result[pos] = input[pos][index];
}
yield return result;
do
{
if (pos == 0) yield break;
index = indices[--pos] + 1;
}
while (index >= input[pos].Count);
}
}
}
combined with simple LINQ:
var fields = mDataFields.Where(x => x.Values.Count > 0).ToList();
var result = fields
.Select(df => df.Values).ToList()
.GenerateCombinations()
.Select(c => c.Select((v, i) => new FieldProperties(fields[i].Name, v)).ToList())
.ToList();
Upvotes: 1