Pair-Wise Iteration in C# or Sliding Window Enumerator

How to make this for loop run between 2 array value (value pair) and iterate through all the elements of that array

Maybe you are looking for:

var array = new []{0,5,8,12};

for (var i = 0; i < array.Length-1; i++)
{
for (var j = array[i]; j < array[i + 1]; j++)
{
Console.Write(j + " ");
}
Console.WriteLine();
}

Output

0 1 2 3 4
5 6 7
8 9 10 11

You could also make yourself an iterator method

public static IEnumerable<(int start, int finish)> GetRange(int[] source)
{
for (var i = 0; i < source.Length - 1; i++)
yield return (source[i], source[i + 1]);
}

Which would allow more enumerable flexibility

var results = GetRange(array)
.Select(x => string.Join(", ", Enumerable.Range(x.start, x.finish-x.start)));

foreach (var result in results)
Console.WriteLine(result);

Output

0, 1, 2, 3, 4
5, 6, 7
8, 9, 10, 11

How do I take two at a time from a collection

If I understand the problem, you just need to jump 2 in a for loop

public static IEnumerable<string> GetSubStrings(string input, List<int> source)
{
for (var i = 0; i < source.Count; i += 2)
yield return input.Substring(source[i], source[i + 1] - source[i]);
}

or if you don't want to use an iterator method

public static List<string> GetSubStrings2(string input, List<int> source)
{
var result = new List<string>();
for (var i = 0; i < source.Count; i += 2)
result.Add(input.Substring(source[i], source[i + 1] - source[i]));
return result;
}

Usage

var input = "2abcdef2ggg2abcdefgh2";
var indexes = AllIndexesOf(input, "2");

Console.WriteLine(string.Join(", ", GetSubStrings(input, indexes)));

Output

2abcdef, 2abcdefgh

Full Demo Here

C# enumerator terminology confusion

Enumarations (enums) are unrelated to Enumerators.

And

I was told that to avoid...

Seems like a very premature and unnecessary optimization.

MongoDB C# Iteration as enumerator

You use ToEnumerable extension method for that and to get only the ID you need to use a projection.

The following code should work

public class MongoAlbum
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Property { get; set; }
}
IMongoClient client;
IMongoDatabase database;
IMongoCollection<MongoAlbum> collection;
client = new MongoClient("connection string");
database = client.GetDatabase("DB name");
collection = database.GetCollection<MongoAlbum>("collection name");
IEnumerable<string> albums = collection.Find(x => x.Id == "1")
.Project(x => x.Id)
.ToEnumerable<string>();

In this case it will be a List of strings since you will only get Ids results and in my MongoAlbum POCO i used a string.

How to Zip one IEnumerable with itself

Also, is there better name for the extension that might reflect that it is a well-known pattern (if, indeed it is a well-known pattern)?

Yes - it is also known as Pairwise. It has been done before, for example here. There also has been a question about it before here on SO.

Pairwise can now be implemented in terms of Zip for .NET 4.0, as you point out. This seems like a reasonable approach for a LINQ to Objects solution, although having a version that works on .NET v3.5 too is probably more useful to a wider audience at this point.

Recursive enumerator

No, unfortunately, there is no way to achieve this.

There is no such thing as yield return many GetNodes(...); and mixing yield return and normal return is also not allowed.

However, you can achieve the desired result (deferred execution) using LINQ:

private static IEnumerable<Node> GetNodes(Node root)
{
var result = Enumerable.Empty<Node>();

if (root.left != null)
result = result.Concat(GetNodes(root.left));

result = result.Concat(new [] { root });

if (root.right != null)
result = result.Concat(GetNodes(root.right));

return result;
}

Whether this is better than what you currently have is debatable.

If you have a LINQ statement using the Select() method, is there a way to get a value from the next record?

Here is a helper function that maps a sequence into a sequence of pairs where each pair is each item paired with the one that follows it.

public static IEnumerable<Tuple<T, T>> WithNext<T>(this IEnumerable<T> source)
{
using (var iterator = source.GetEnumerator())
{
if(!iterator.MoveNext())
yield break;

T previous = iterator.Current;
while (iterator.MoveNext())
{
yield return Tuple.Create(previous, iterator.Current);
previous = iterator.Current;
}

yield return Tuple.Create(previous, default(T));
}
}

Now you can do:

var query = bookmarkCollection.AsEnumerable()
.WithNext()
.Select(pair => new Statement(){
Title= pair.Item1.Title,
PageNumber = pair.Item1.PageNumber,
NextPageNumber = pair.Item2.PageNumber - 1, //note you'll need to null check for the last item
});


Related Topics



Leave a reply



Submit