Alternative IEnumerable <T> .Skip (1) .Take (1) .Single ()
I have a difficult time with an seemingly easy and embarrassing problem. All I want is the next element in IEnumberable without using Skip (1) .Take (1) .Single (). This example illustrates the main problem.
private char _nextChar;
private IEnumerable<char> getAlphabet()
{
yield return 'A';
yield return 'B';
yield return 'C';
}
public void sortAlphabet()
{
foreach (char alpha in getAlphabet())
{
switch (alpha)
{
case 'A': //When A pops up, I want to get the next element, ie 'B'
_nextChar = getAlphabet().Skip(1).Take(1).Single();
break;
case 'B': //When B pops up, I want 'C' etc
_nextChar = getAlphabet().Skip(1).Take(1).Single();
break;
}
}
}
Besides ugliness, this example works. But let's say that IEnumerable contained 2 million elements, then the LINQ statement forces the program to perform unbearably slow work. I want it simply. I just need the next element in IEnumberable <>. All my problems will be solved if a function such as:
_nextChar = getAlphabet().moveNext() //or getNext()
, // , . , 2 , "money = 324", "" "324" IEnumberable, "", , 324". ( ?: D .)
, , :
_nextChar = getAlphabet().moveNext() //or getNext()
. IEnumerator<T>, IEnumerable<T>!
private char _nextChar;
private IEnumerable<char> getAlphabet()
{
yield return 'A';
yield return 'B';
yield return 'C';
}
public void sortAlphabet()
{
using (var enumerator = getAlphabet().GetEnumerator())
{
while (enumerator.MoveNext())
{
char alpha = enumerator.Current;
switch (alpha)
{
case 'A':
if (enumerator.MoveNext())
{
_nextChar = enumerator.Currrent;
}
else
{
// You decide what to do in this case.
}
break;
case 'B':
// etc.
break;
}
}
}
}
. , IEnumerable<char>, IList<char>? , , , , , getAlphabet ( - , ElementAt, , ).
, , :
private char _nextChar;
private IList<char> getAlphabet()
{
return Array.AsReadOnly(new[] { 'A', 'B', 'C' });
}
public void sortAlphabet()
{
IList<char> alphabet = getAlphabet();
for (int i = 0; i < alphabet.Count - 1; ++i)
{
char alpha = alphabet[i];
switch (alpha)
{
case 'A':
_nextChar = alphabet[i + 1];
break;
case 'B':
// etc.
break;
}
}
}
?
, MoveNext(), IEnumerator<T>, IEnumerable<T>.GetEnumerator(). , MoveNext() Current "".
, foreach getAlphabet(), , :
public static IEnumerable<T[]> InPairsOfTwo<T>(this IEnumerable<T> enumerable)
{
if (enumerable.Count() < 2) throw new ArgumentException("...");
T lastItem = default(T);
bool isNotFirstIteration = false;
foreach (T item in enumerable)
{
if (isNotFirstIteration)
{
yield return new T[] { lastItem, item };
}
else
{
isNotFirstIteration = true;
}
lastItem = item;
}
}
:
foreach (char[] letterPair in getAlphabet().InPairsOfTwo())
{
char currentLetter = letterPair[0],
nextLetter = letterPair[1];
Console.WriteLine("# {0}, {1}", currentLetter, nextLetter);
}
:
# A, B
# B, C
( , , , ! , , , . , , .)
, . , , . , , , . .
enum State
{
Scan,
SaveAndExit
};
public void SortAlphabet()
{
State state = State.Scan; // initialize
foreach(char c in getAlphabet())
{
switch (state):
{
case State.Scan:
if (c == 'A' ||
c == 'B')
state = State.SaveAndExit;
break;
case State.SaveAndExit:
return (c);
break;
}
}
}
.NET 4.0, , , :
var alphabet = getAlphabet();
var offByOneAlphabet = alphabet.Skip(1);
foreach (var pair in alphabet.Zip(offByOneAlphabet, (a, b) => Tuple.Create(a, b)))
Console.WriteLine("Letter: {0}, Next: {1}", pair.Item1, pair.Item2);
// prints:
// Letter: A, Next: B
// Letter: B, Next: C
- , .NET 4.0, Zip Tuple.