To start with I\'ll say that I agree that goto statements are largely made irrelevant by higher level constructs in modern programming languages and shouldn\'t be used when
Personally I like Mark Byer's option, but you could always write your own generic method for this:
public static void IterateWithSpecialFirst<T>(this IEnumerable<T> source,
Action<T> firstAction,
Action<T> subsequentActions)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if (iterator.MoveNext())
{
firstAction(iterator.Current);
}
while (iterator.MoveNext())
{
subsequentActions(iterator.Current);
}
}
}
That's relatively straightforward... giving a special last action is slightly harder:
public static void IterateWithSpecialLast<T>(this IEnumerable<T> source,
Action<T> allButLastAction,
Action<T> lastAction)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
return;
}
T previous = iterator.Current;
while (iterator.MoveNext())
{
allButLastAction(previous);
previous = iterator.Current;
}
lastAction(previous);
}
}
EDIT: As your comment was concerned with the performance of this, I'll reiterate my comment in this answer: while this general problem is reasonably common, it's not common for it to be such a performance bottleneck that it's worth micro-optimizing around. Indeed, I can't remember ever coming across a situation where the looping machinery became a bottleneck. I'm sure it happens, but that isn't "common". If I ever run into it, I'll special-case that particular code, and the best solution will depend on exactly what the code needs to do.
In general, however, I value readability and reusability much more than micro-optimization.
I prefer first
variable method. It is probably not cleanest but most efficient way. Alternatively you could use Length
of the thing you appending to and compare it to zero. Works well with StringBuilder
.
Why don't move dealing with first element outside a loop ?
StringBuilder sb = new StrindBuilder()
sb.append(array.first)
foreach (var elem in array.skip(1)) {
sb.append(",")
sb.append(elem)
}
For your specific example there is a standard solution: string.Join
. This handles adding the delimiter correctly so that you don't have to write the loop yourself.
If you really want to write this yourself an approach you can use is the following:
string delimiter = "";
foreach (var element in array)
{
append(delimiter);
append(element);
delimiter = ",";
}
This should be reasonably efficient and I think it is reasonable to read. The constant string "," is interned so this won't result in a new string being created on each iteration. Of course if performance is critical for your application you should benchmark rather than guess.
Sometimes I use LINQ .First()
and .Skip(1)
to handle this ... This can give a relatively clean (and very readable) solution.
Using you example,
append(array.First());
foreach(var x in array.Skip(1))
{
append(delimiter);
append (x);
}
[This assumes there is at least one element in the array, an easy test to add if that's to be avoided.]
Use F# would be another suggestion :-)
You are already willing to give up on foreach. So this ought to be suitable:
using (var enumerator = array.GetEnumerator()) {
if (enumerator.MoveNext()) {
for (;;) {
append(enumerator.Current);
if (!enumerator.MoveNext()) break;
append(delimiter);
}
}
}