5
\$\begingroup\$

I have some code that loops over a number and populates a list using other lists. I think I can refactor it somehow to make it look nicer but not sure the best way to do it.

Here is the code:

for (int i = 0; i < loopCount; i++)
{
 switch (NoOfRows)
 {
 case 1:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]); 
 break;
 case 2:
 if (InputList1.Count > i) 
 ExpectedValues.Add(InputList1[i]); 
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 break;
 case 3:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 break;
 case 4:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 break;
 case 5:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 break;
 case 6:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 if (InputList6.Count > i)
 ExpectedValues.Add(InputList6[i]);
 break;
 case 7:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 if (InputList6.Count > i)
 ExpectedValues.Add(InputList6[i]);
 if (InputList7.Count > i)
 ExpectedValues.Add(InputList7[i]);
 break;
 case 8:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 if (InputList6.Count > i)
 ExpectedValues.Add(InputList6[i]);
 if (InputList7.Count > i)
 ExpectedValues.Add(InputList7[i]);
 if (InputList8.Count > i)
 ExpectedValues.Add(InputList8[i]);
 break;
 case 9:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 if (InputList6.Count > i)
 ExpectedValues.Add(InputList6[i]);
 if (InputList7.Count > i)
 ExpectedValues.Add(InputList7[i]);
 if (InputList8.Count > i)
 ExpectedValues.Add(InputList8[i]);
 if (InputList9.Count > i)
 ExpectedValues.Add(InputList9[i]);
 break;
 case 10:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 if (InputList3.Count > i)
 ExpectedValues.Add(InputList3[i]);
 if (InputList4.Count > i)
 ExpectedValues.Add(InputList4[i]);
 if (InputList5.Count > i)
 ExpectedValues.Add(InputList5[i]);
 if (InputList6.Count > i)
 ExpectedValues.Add(InputList6[i]);
 if (InputList7.Count > i)
 ExpectedValues.Add(InputList7[i]);
 if (InputList8.Count > i)
 ExpectedValues.Add(InputList8[i]);
 if (InputList9.Count > i)
 ExpectedValues.Add(InputList9[i]);
 if (InputList10.Count > i)
 ExpectedValues.Add(InputList10[i]);
 break;
 }
}
palacsint
30.3k9 gold badges82 silver badges157 bronze badges
asked Apr 26, 2012 at 13:17
\$\endgroup\$
8
  • \$\begingroup\$ And how/where are InputList1..10 defined? \$\endgroup\$ Commented Apr 26, 2012 at 13:20
  • \$\begingroup\$ You can put all InputLists into array of inputLists and use a simple for \$\endgroup\$ Commented Apr 26, 2012 at 13:20
  • \$\begingroup\$ @Jamiec Not sure how to move it, copy & paste? \$\endgroup\$ Commented Apr 26, 2012 at 13:21
  • \$\begingroup\$ @sinelaw they are class properties \$\endgroup\$ Commented Apr 26, 2012 at 13:21
  • \$\begingroup\$ @Jon, ok but why do you define them like that? Why not make a list of lists? \$\endgroup\$ Commented Apr 26, 2012 at 13:22

3 Answers 3

2
\$\begingroup\$

The alternate method of Dr. Andrew Burnett-Thom would be to use a Dictionary<int, InputList>:

 var dic = new Dictionary<int, InputList>();
 // add InputLists
 dic.Add(0, InputList1);
 dic.Add(1, InputLIst2);
 //etc...
 for( int i = 0; i < loopCount; i++ )
 {
 for( int j = 0; j < NoOfRows; j++ )
 {
 if( dic[j].Count > i )
 {
 ExpectedValues.Add( dic[j][i] );
 }
 }
 }
answered Apr 26, 2012 at 13:39
\$\endgroup\$
5
  • \$\begingroup\$ Except you need to index into dic[j] to get the value. \$\endgroup\$ Commented Apr 26, 2012 at 13:44
  • \$\begingroup\$ @Khanzor I'm not following... what do you mean? \$\endgroup\$ Commented Apr 26, 2012 at 13:47
  • \$\begingroup\$ The result of dic[j] will be an InputList, you want the ith value of that list, right? \$\endgroup\$ Commented Apr 26, 2012 at 13:48
  • \$\begingroup\$ @Khanzor good catch! \$\endgroup\$ Commented Apr 26, 2012 at 13:53
  • \$\begingroup\$ Not sure why the downvote... oh well. \$\endgroup\$ Commented Apr 26, 2012 at 13:55
1
\$\begingroup\$

Yes, a very simple way to do this is to have a number of methods and store delegates to them in a dictionary, keyed on NumberOfRows.

It'll look prettier but doesn't add any functional benefit. For instance:

 switch (NoOfRows)
 {
 case 1:
 if (InputList1.Count > i)
 ExpectedValues.Add(InputList1[i]); 
 break;
 case 2:
 if (InputList1.Count > i) 
 ExpectedValues.Add(InputList1[i]); 
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
 break;

Becomes

Dictionary<int, Action<int>> _operations;
public void Foo()
{
 // Create methods and store in a dictionary once
 if (_operations == null)
 {
 _operations = new Dictionary<int, Action>();
 _operations.Add(1, ProcessOneRow); 
 _operations.Add(2, ProcessTwoRows); 
 // ... 
 }
 for (int i = 0; i < loopCount; i++)
 {
 // Invoke the delegate to the correct method
 var operation = _operations[NoOfRows];
 operation(i);
 }
}
public void ProcessOneRow(int i)
{
 if (InputList1.Count > i) ExpectedValues.Add(InputList1[i]);
}
public void ProcessTwoRows(int i)
{ 
 ProcessOneRow(i);
 if (InputList2.Count > i)
 ExpectedValues.Add(InputList2[i]);
}

To be honest looking at the above you ought to move your delegate lookup outside of the loop if NoOfRows does not change inside the loop.

answered Apr 26, 2012 at 13:25
\$\endgroup\$
4
  • 1
    \$\begingroup\$ I was about to post something similar; Instead of an Action as the value in the Dictionary, use the InputListx. Then based on the number of rows, perform the same action on each list for i to n. The patter in the OP is each list is doing the same thing. \$\endgroup\$ Commented Apr 26, 2012 at 13:28
  • 1
    \$\begingroup\$ Aha yes, flip-side of the coin. I didn't notice the InputLists were just incrementing each time. I suppose the correct answer to this question is going to be "Do what is readable and simple for developers to understand". If it's too funky then it detracts from code readability and might not be that valuable! \$\endgroup\$ Commented Apr 26, 2012 at 13:30
  • 1
    \$\begingroup\$ @MetroSmurf Post your answer! \$\endgroup\$ Commented Apr 26, 2012 at 13:38
  • \$\begingroup\$ @Jon - posted and done. \$\endgroup\$ Commented Apr 26, 2012 at 13:39
1
\$\begingroup\$

What about some Linq?

var allInputLists = new List<List<T>>
{
 InputList1, InputList2, 
 InputList3, InputList4, 
 InputList5, InputList6, 
 InputList7, InputList8, 
 InputList9, InputList10
};
var expectedValues = from i in Enumerable.Range(0, loopCount)
 from list in allInputLists.Take(NoOfRows - 1)
 where list.Count > i
 select list[i];

Or, in fluent syntax:

var expectedValues = Enumerable.Range(0, loopCount)
 .SelectMany(i => allInputLists.Take(NoOfRows - 1)
 .Where(list => list.Count > i)
 .Select(list => list[i])
 );

Although the query syntax in this case is a bit nicer.

answered Apr 26, 2012 at 13:27
\$\endgroup\$
2
  • 1
    \$\begingroup\$ can't quite see whats going on here, could you explain it more or use fluent linq? \$\endgroup\$ Commented Apr 26, 2012 at 13:33
  • \$\begingroup\$ Enumerable.Range is like your for loop, and for each of the values that are generated, that walks through all the lists (so a nested for loop) up to the NoOfRows, checks that they have more elements than the current i, and "joins" together all those elements to build your ExpectedValues from scratch. \$\endgroup\$ Commented Apr 26, 2012 at 13:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.