Move items in the array of strings to the left to fill the "holes"
I have a list of names and phones like:
var phonelist = List<string[]>
{
new string[] {"Bill", "1234", "12345", "12314" },
new string[] {"Bob", "", "12345", "12314" },
new string[] {"Chris", "", "", "12314" },
new string[] {"Dave", "1234", "", "12314" },
new string[] {"Andy", "1234", "12345", "" },
}
What is the most efficient / elegant way to process this list so that the "empty" numbers are filled on the right?
Note that arrays must be the same length, for example:
var phonelist = List<string[]>
{
new string[] {"Bill", "1234", "12345", "12314" },
new string[] {"Bob", "12345", "12314", "" },
new string[] {"Chris", "12314", "", "" },
new string[] {"Dave", "1234", "12314", "" },
new string[] {"Andy", "1234", "12345", "" },
}
for each cell of the array, check if it was empty and replaced with cell + 1, if it is still empty, replace it with cell + 2 .. when the cell becomes empty, do the same with cell + 2 ...
int j;
foreach (string[] strs in phoneList)
{
for (int i = 0; i < strs.Length; i++)
{
j = 1;
while (string.IsNullOrEmpty(strs[i]) && j < strs.Length - i)
{
if (!string.IsNullOrEmpty(strs[i + j])) // to not swap 2 empty strings
{
strs[i] = strs[i + j];
strs[i + j] = "";
}
j++;
}
}
}
- :
Comparison<string> comparison = (x,y) =>
{
if (String.IsNullOrEmpty(x))
return 1;
if (String.IsNullOrEmpty(y))
return -1;
return String.Compare(x,y);
}
foreach (string[] array in phoneList)
{
Array.Sort(array, comparison);
}
,
EDIT: since the name is always the first element, another option is to exclude it from sorting. No Array.Sortoverload accepts Comparison<T>and range, so instead you should use IComparer<T>:
class MyComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (String.IsNullOrEmpty(x))
return 1;
if (String.IsNullOrEmpty(y))
return -1;
return String.Compare(x,y);
}
}
foreach (string[] array in phonelist)
{
Array.Sort(array, 1, array.Length - 1, new MyComparer());
}
List<string[]> sorted = new List<string[]>();
foreach (string[] entry in phoneList)
{
List<string> nonEmpty = (from s in entry
where String.IsNullOrEmpty(s) == false
select s).ToList();
int pad = entry.Length - nonEmpty.Count;
List<string> pads = new List<string>();
while (pad > 0)
{
pads.Add(String.Empty);
--pad;
}
List<string> sortedEntry = new List<string>();
sortedEntry.AddRange(nonEmpty);
sortedEntry.AddRange(pads);
sorted.Add(sortedEntry.ToArray());
}