1

I need to find a way of condensing a large number of foreach loops down into one easy to manage function if possible.

The following example provides two loops which create combinations of their respective values for each iteration.

The problem is that there could be up to 30 loops and this has lead to unsightly code that is hard to manage.

//Setting up house instances
House house1 = new House();
house1.DoorNumber = 2;

House house2 = new House();
house2.DoorNumber = 3;

//Adding these to a list
List<House> _houseList = new List<House>();
_houseList.Add( house1 );
_houseList.Add( house2 );

//Setting up street instances
Street street1= new Street ();
street1.Name = "Wildflower Street";

Street street2 = new Street();
street2.Name = "Teras Kasi Street";

//Again adding these to a list
List<Street > _streetList = new List<Street >();
_streetList .Add( street1 );
_streetList .Add( street2 );


//Now the question, these loops will grow exponentially
foreach( House house in _houseList )
{
   foreach( Street street in _streetList )
   {
     Address address = new Address();
     address.House = house;
     address.Street = street;

     Console.WriteLine( address.House.DoorNumber.ToString() + " " + address.Street.StreetName  );
   }
}

Expected Output

2 Wildflower Street

2 Teras Kasi Street

3 Wildflower Street

3 Teras Kasi Street

The output is simply for clarification of how the Address objects should look in memory.


Please Note

The question is not a duplicate, all other questions I have seen posted on SO have asked to print and concatenate string/integers. This question asks how to add combinations of objects to properties of another class using lists.

Master Yoda
  • 4,334
  • 10
  • 43
  • 77
  • 1
    The duplicate question shows you how to do what you're asking for. The fact that the results are used differently is irrelevant to both questions. – Servy May 06 '15 at 15:19
  • @Servy Actually thats not true, irrelevance would suggest that an answer is provided ( which may be true ) but how to use that answer is not. The accepted answer provided in the duplicate takes a list of integers not generic types. Also the solution itself is complex enough not to find the solution you claim is present. – Master Yoda May 06 '15 at 16:09
  • So you're saying it's impossible for you to read past the accepted answer and see ready any of the other 4 answers, 3 of which answer your question exactly? – Servy May 06 '15 at 16:15
  • Actually what im saying is this. Which one of any of the answers provides an example of how to solve my problem? If you check Rawlings solution you will notice that I also asked for an example of how to solve this. Im saying im not sure of the syntax to use the solution. So no its not impossible just a little hard for me to get my head around. – Master Yoda May 06 '15 at 16:23

1 Answers1

1

Here's a non recursive cartesian product version (only tested in Mono):

class MainClass
{
    static void Main()
    {
        var houses = new [] {
            new { number = 1 },
            new { number = 2 }
        };

        var streets = new[] {
            new { name = "AAA" },
            new { name = "BBB" }
        };

        var q = CartesianProduct (
            houses.Select (x => x.number.ToString()),
            streets.Select (x => x.name)
        );

        foreach( var item in q )
            Console.WriteLine(string.Join(" ", item));
    }


    static IEnumerable<IEnumerable<T>> CartesianProduct<T>(params IEnumerable<T>[] lists) 
    {
        IEnumerable<IEnumerable<T>> result = new[]{ new T[]{} }; 
        foreach(var list in lists) 
            result = from previous in result 
                    from current in list
                    select previous.Concat(new[] {current}); 
        return result; 
    }   
}
Juan Lopes
  • 10,143
  • 2
  • 25
  • 44