Title: Enumerate pairs of objects in arrays or IEnumerables in C#
Sometimes it's useful to enumerate pairs of objects in an array or enumerable. For example, if you have an array holding volleyball teams, the pairs would list each of the possible matches you could make. If the teams are A, B, C, and D, then the pairs include (A, B), (A, C), (A, D), (B, C), (B, D), and (C, D).
This example demonstrates two extension methods, one for arrays and one for objects that implement IEnumerable, that build lists of the possible pairs.
The lists those methods return contain instances of the following Pair structure.
public struct Pair<T>
{
// Values.
public T Value1, Value2;
// Constructor.
public Pair(T value1, T value2)
{
Value1 = value1;
Value2 = value2;
}
// Default ToString method.
public override string ToString()
{
return Value1.ToString() + ", " + Value2.ToString();
}
}
This structure's Value1 and Value2 fields contain the values that make up the pair. The structure defines a constructor to make creating pairs easier. It also defines a default ToString method that simply returns the pair's values converted into strings and separated by a comma.
The following code shows the first extension method, which generates pairs for an array.
// Return a list of unique unordered pairs of items
// taken from an array.
public static List<Pair<T>> Pairs<T>(this T[] items)
{
List<Pair<T>> results = new List<Pair<T>>();
for (int i = 0; i < items.Length - 1; i++)
for (int j = i + 1; j < items.Length; j++)
results.Add(new Pair<T>(items[i], items[j]));
return results;
}
This method creates a results list to hold the pairs. It then uses a for loop with variable i ranging from 0 to the second-to-last index in the array. For each i value, it uses another for loop with variable j ranging from i + 1 to the last index in the array. Those loops generate every unique unordered pair of indexes i and j.
For each value of i and j, the code creates a Pair holding the corresponding items from the array and adds the Pair to the results list. After it finishes adding all of the pairs, the method returns the list.
The following code shows the second extension method, which generates pairs for an IEnumerable.
// Return a list of unique unordered pairs of items
// taken from an IEnumerable.
public static List<Pair<T>> Pairs<T>(this IEnumerable<T> items)
{
return items.ToArray().Pairs();
}
This method simply uses the ToArray method to convert the IEnumerable into an array and then uses the first extension method generate the pairs.
The following code shows how the main program demonstrates the extension methods.
private void Form1_Load(object sender, EventArgs e)
{
// Display the original values.
string[] value_array =
{
"Ankylosaurus", "Brachiosaurus", "Caenagnathus",
"Diplodocus", "Enigmosaurus","Fabrosaurus",
};
lstValues.DataSource = value_array;
// Display pairs from the array.
foreach (PairsTools.Pair<string> pair in value_array.Pairs())
lstFromArray.Items.Add(pair);
// Make a list holding the values.
List<string> value_list = new List<string>();
foreach (string value in value_array) value_list.Add(value);
// Display pairs from the list.
foreach (PairsTools.Pair<string> pair in value_list.Pairs())
lstFromIEnumerable.Items.Add(pair);
}
The code first builds an array of strings. It then uses the first version of the extension method and loops through the result, adding the pair objects to the lstFromArray ListBox. The ListBox figures out what to display for an item by calling its ToString method. The Pair structure's ToString method returns the values of the items it contains separated by a comma, so the result in this example is the list of string pairs you can see in the picture above.
Next the program builds a List<string>, copies the strings from the array into the list, and then uses the second version of the extension method to generate and display pairs from the list.
Download the example to experiment with it and to see additional details.
|