Reputation: 424
I am having a brain freeze and just cant figure out a solution to this problem.
I created a class called CustomSet that contained a string list. The class holding a reference to CustomSet stores it as a list.
public class CustomSet : IEnumerable<string>
{
public string Name { get; set; }
internal IList<string> elements;
public CustomSet(string name)
{
this.Name = name;
this.elements = new List<string>();
}
public IEnumerable<string> Elements
{
get
{
return elements;
}
}
public IEnumerator<string> GetEnumerator()
{
return elements.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
So what I would like to do is iterate over this list of custom sets to out put a 2d string array where the columns are the number of customSet(s) and the rows are a multiplication of the customSet elements.
As an example, if there were 3 custom sets in the list: 1st had 3 elements, 2nd had 2 elements and 3rd had 3 elements. I would want to output 3 columns and 18 rows (3*2*3). The following code is an attempt at the solution:
CustomSet motion = new CustomSet("Motion");
motion.Elements.Add("low");
motion.Elements.Add("medium");
motion.Elements.Add("high");
CustomSet speed = new CustomSet("Speed");
speed.Elements.Add("slow");
speed.Elements.Add("Fast");
CustomSet mass = new CustomSet("Mass");
mass.Elements.Add("light");
mass.Elements.Add("medium");
mass.Elements.Add("heavy");
List<CustomSet> aSet = new List<CustomSet>();
aSet.Add(motion);
aSet.Add(speed);
aSet.Add(mass);
//problem code
int rows = 1;
for(int i = 0; i < aSet.Count; i++)
{
rows *= aSet[i].Elements.Count;
}
string[,] array = new String[aSet.Count, rows];
int modulus;
for (int i = 0; i < aSet.Count; i++)
{
for (int j = 0; j < rows; j++)
{
modulus = j % aSet[i].Elements.Count;
array[i, j] = aSet[i].Elements[modulus];
}
}
for (int j = 0; j < rows; j++)
{
for (int i = 0; i < aSet.Count; i++)
{
Console.Write(array[i, j] + " / ");
}
Console.WriteLine();
}
//end
Console.ReadLine();
However, the code does not output the correct string array (though it is close). What I would like it to out put is the following:
low / slow / light /
low / slow / medium /
low / slow / heavy /
low / Fast / light /
low / Fast / medium /
low / Fast / heavy /
medium / slow / light /
medium / slow / medium /
medium / slow / heavy /
medium / Fast / light /
medium / Fast / medium /
medium / Fast / heavy /
high / slow / light /
high / slow / medium /
high / slow / heavy /
high / Fast / light /
high / Fast / medium /
high / Fast / heavy /
Now the variables in this problem is the number of customSets in the list and the number of elements in each CustomSet.
Upvotes: 0
Views: 3684
Reputation: 3154
This recursive approach shows the results as desired, with a list of n CustomSet objects:
void OutputSets(List<CustomSet> aSet, int setIndex, string hirarchyString)
{
string ouputString = hirarchyString;
int nextIndex = setIndex + 1;
foreach (string element in aSet[setIndex].Elements)
{
if (nextIndex < aSet.Count)
{
OutputSets(aSet, nextIndex, hirarchyString + element + " / ");
}
else
{
Console.WriteLine(ouputString + element + " / ");
}
}
}
Call it with:
OutputSets(aSet, 0, "");
Upvotes: 1
Reputation: 499002
You can get the product in one go:
var crossJoin = from m in motion
from s in speed
from ms in mass
select new { Motion = m, Speed = s, Mass = ms };
foreach (var val in crossJoin)
{
Console.Write("{0} / {1} / {2}", val.Motion, val.Speed, val.Mass);
}
Now, since you don't know the number of lists, you need to do some more. Eric Lippert covers this in this article, where you can use the CertesianProduct
function defined there in the following manner:
var cProduct = SomeContainerClass.CartesianProduct(aSet.Select(m => m.Elements));
var stringsToOutput = cProduct.Select(l => string.Join(" / ", l));
Upvotes: 7