Best way to set IEnumerator to end - c#

I have custom class that implement IEnumerable<int[]> interface and save current Enumerator. When added new element I need set enumerator to last element.
Sample code for set enumerator to end:
IEnumerable<int> seq = ...
seq.Reset();
for (int i = 0; i < seq.Count; i++)
{
seq.MoveNext();
}
How do this faster?
(Can I go to the end can't not scroll all sequence elements?)

if faster means less code (another alternative is),
IEnumerable<int> seq = ...
while (seq.MoveNext())
{
var item = seq.Current;
}
EDIT
you want seq.Last()
It is an extension method and has code similar to above.
EDIT2
i need seq.Current=seq.Last();
your code is similar to
IEnumerable<int> seq = ...
int count=0;
//Following while is equivalent to seq.Count
while (seq.MoveNext())
{
count++;
}
int i=0;
while (i<count)
{
seq.MoveNext();
}
Using IEnumerator only it is not possible to set seq.Current to Last in one iteration as you never know where to stop.

The for statement will iterate from x to y, with a pre-defined increment, like so:
for (`start`; `until`; `increment`)
e.g. If we wanted to loop from 0 to 9, with an increment of 1, we would write
for (int i = 0; i < 10; i++)
If you have an object that implements a next type method, you may want to use a while loop.
while (seq.CurrentItem != null)
{
// do something with the current item and move to next
seq.Next();
}
I would recommend reading up about loops in C#.

Related

Combination of a list of lists so that each combination has unique elements

Ok so, I have a list of lists, like the title says and I want to make combinations of k lists in which every list has different elements than the rest.
Example:
I have the following list of lists:
{ {1,2,3} , {1,11} , {2,3,6} , {6,5,7} , {4,8,9} }
A valid 3-sized combination of these lists could be:
{ {1,11}, {4,8,9} ,{6,5,7} }
This is only ONE of the valid combinations, what I want to return is a list of all the valid combinations of K lists.
An invalid combination would be:
{ {1,11} ,{2, 3, 6}, {6, 5, 7} }
because the element 6 is present in the second and third list.
I already have a code that does this but it just finds all possible combinations and checks if they are valid before addding it to a final result list. As this list of lists is quite large (153 lists) when K gets bigger, the time taken is ridiculously big too (at K = 5 it takes me about 10 minutes.)
I want to see if there's an efficient way of doing this.
Below is my current code (the lists I want to combine are attribute of the class Item):
public void recursiveComb(List<Item> arr, int len, int startPosition, Item[] result)
{
if (len == 0)
{
if (valid(result.ToList()))
{
//Here I add the result to final list
//valid is just a function that checks if any list has repeated elements in other
}
return;
}
for (int i = startPosition; i <= arr.Count - len; i++)
{
result[result.Length - len] = arr[i];
recursiveComb(arr, len - 1, i + 1, result);
}
}
Use a HashSet
https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx
to keep track of distinct elements as you build the output from the candidates in the input list of lists/tuples
accumulate an output list of non overlapping tuples by Iterating across the input list of tuples and evaluate each tuple as a candidate as follows:
For each input tuple, insert each tuple element into the HashSet. If the element you are trying to insert is already in the set, then the tuple fails the constraint and should be skipped, otherwise the tuple elements are all distinct from ones already in the output.
The hashset object effectively maintains a registry of distinct items in your accepted list of tuples.
If I understood your code correctly then, you are passing each list<int> from your input to recursiveComb() function. which look like this
for(int i = 0; i < inputnestedList.Count; i++)
{
recursiveComb();
// Inside of recursiveComb() you are using one more for loop with recursion.
// This I observed from your first parameter i.e. List<int>
}
Correct me if I am wrong
This leads to time complexity more than O(n^2)
Here is my simplest solution, with two forloops without recursion.
List<List<int>> x = new List<List<int>>{ new List<int>(){1,2,3} , new List<int>(){1,11} , new List<int>(){2,3,6} , new List<int>(){6,5,7} , new List<int>(){4,8,9} };
List<List<int>> result = new List<List<int>>();
var watch = Stopwatch.StartNew();
for (int i = 0; i < x.Count;i++)
{
int temp = 0;
for (int j = 0; j < x.Count; j++)
{
if (i != j && x[i].Intersect(x[j]).Any())
temp++;
}
// This condition decides, that elements of ith list are available in other lists
if (temp <= 1)
result.Add(x[i]);
}
watch.Stop();
var elapsedMs = watch.Elapsed.TotalMilliseconds;
Console.WriteLine(elapsedMs);
Now when I print execution time then output is
Execution Time: 11.4628
Check execution time of your code. If execution time of your code is higher than mine, then you can consider it as efficient code
Proof of code: DotNetFiddler
Happy coding
If I understood your problem correctly then this will work:
/// <summary>
/// Get Unique List sets
/// </summary>
/// <param name="sets"></param>
/// <returns></returns>
public List<List<T>> GetUniqueSets<T>(List<List<T>> sets )
{
List<List<T>> cache = new List<List<T>>();
for (int i = 0; i < sets.Count; i++)
{
// add to cache if it's empty
if (cache.Count == 0)
{
cache.Add(sets[i]);
continue;
}
else
{
//check whether current item is in the cache and also whether current item intersects with any of the items in cache
var cacheItems = from item in cache where (item != sets[i] && item.Intersect(sets[i]).Count() == 0) select item;
//if not add to cache
if (cacheItems.Count() == cache.Count)
{
cache.Add(sets[i]);
}
}
}
return cache;
}
Tested, it's fast and took 00:00:00.0186033 for finding sets.

Check if all elements in an array are equal

In the first part I am creating pairs out of array elements and the array is twice as short. The array is always even.
Here is the first part:
using System;
class Program
{
static void Main()
{
int[] Arr = new int[]{1, 2, 0, 3, 4, -1};
int[] newArr = new int[(Arr.Length / 2)];
int sum = 0;
for (int i = 0; i < Arr.Length; i+=2)
{
if (i + 1 < Arr.Length)
{
newArr[sum] = Arr[i] + Arr[i + 1];
}
else
{
newArr[sum] = Arr[i];
}
sum++;
}
in the second part I would like to check if the array elements are equal. What I want to do is to increment int counter each time the index in the for loop is equal to the next index in the array.
What I have as second part:
int counter = 0;
for (int i = 0; i < newArr.Length -1; i++)
{
if (newArr[i] == newArr[i + 1])
{
counter++;
}
else
{
Console.Write(" ");
}
}
What is wrong in this code. I cannot seem to understand how to write code that will work with int Arr[5] and int Arr[5000]
All you need to change is the termination condition in the for loop to
i < newArr.Length - 1
so that you can compare array[i] with array[i + 1]. This change makes sure you do not get past the upper bound of the array.
try this
for ( i=1;i<arr.Length;i++)
{
if(arr[0]==arr[i])
continue;
else
break;
}
if (i==arr.Length)
Console.WriteLine("All element in array are equal");
If there is no need to write so imperative code, other than to achieve your final goal – you don't have to. Almost always you can do it in a much more readable way.
I suggest using LINQ. For collections implementing IEnumerable<T>:
newArr.Distinct().Take(2).Count() == 1
LINQ is a built-in feature, just make sure you are using System.Linq; at the top of your .cs file.
What goes on here?
Distinct returns an IEnumerable<T>, its enumeration will give all distinct elements from your array, but no enumeration, and hence computation, happened yet.
Take returns new IEnumerable<T>, its enumeration will enumerate previous IEnumerable<T> internally, but it will give only first two distinct elements. Again, no enumeration happened yet.
At last, Count enumerates the last IEnumerable<T> and returns its elements count (in our case 0, 1 or 2).
As we used Take(2), the enumeration initiated by Count method will be stopped right when the second distinct element is found. If we don't use Take(2), our code will enumerate the whole array even if it is not needed.
Why is this approach better?
Much shorter and more readable;
Lazy evaluation – if an element is found out to be distinct from the other ones, the enumeration will be stopped immediately;
Flexible – you can pass a custom equality comparer to Distinct method. You can also call Select method before calling Distinct to choose what specific member your elements will be compared by;
Universal – Works with any collection which impletents IEnumerable<T> interface.
Other ways
The same result can be achieved in slightly other ways, for example:
!newArr.Distinct().Take(2).Skip(1).Any()
Experiment with LINQ and choose the way you and your team consider the most readable.
For collections implementing IList<T> you can also write (as #Alexander suggested):
newArr.All(x => x == newArr[0])
This variant is shorter but not as flexible and universal.
OFF TOPIC. Encapsulating common code
You should encapsulate code that does one simple thing into a separate method, it further improves your code readability and allows reusing your method in several places. I'd write an extension method for this one.
public static class CollectionExtensions {
public static bool AllElementsEqual<T>(this IEnumerable<T> items) {
return items.Distinct().Take(2).Count() == 1;
}
}
Later in your code you need just to call this method:
newArr.AllElementsEqual()
Try this..
for (int i = 0; i < newArr.Length-1; i++)
{
for(int j=0 ;j< newArr.Length-1; i++)
{
if (newArr[i] == newArr[j])
{
/////
}
}
}
else
{
Console.Write(" ");
}
}

List's ForEach() method not acting as expected

Why is this not working?
List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
test.Add(i);
test.ForEach(t => t = ++t);
The elements in test are not incremented.
Firstly, List<T>.ForEach isn't part of LINQ. It's been in .NET since 2.0.
Elements in test are not incremented
No, they wouldn't be. The parameter to Action<T> is passed by value, not by reference. Changes made to the parameter (t in your case) aren't visible to the calling code - and even if they were, there's no guarantee that List<T>.ForEach would use them.
Note that if you had a reference type (e.g. StringBuilder) as the list element type, and made changes to the data in the object that the parameter value referred to, e.g.
builders.ForEach(x => x.Append("Foo"))
then those changes would be visible in the list, because they're not changes to the list at all - the list would contain the same references as before, just to objects whose data happened to have changed.
Ints are values, not references.
Plus a foreach doesn't allow manipulation of the collection elements.
So it's a double fail i'm afraid :(
What would work:
for(int i=0;i<test.Count;i++)
test[i]++;
The t variable that you have is a copy of the item in the list. You are modifying a copy, and as such the item in the list itself isn't affected. To increment each item in the list you can use a for loop:
for(int i = 0; i < test.Count;i++
test[i]++;
This is the expected result.
You wouldn't expect the following to actually increment x in Main, so your lambda example is no different.
static void Main(string[] args)
{
int x = 1;
Increment(x);
Console.WriteLine("{0}");
}
static void Increment(int x)
{
x = ++x;
}
List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
test.Add(i);
for(var z = 0 ; z < test.Count; z++)
{
test[z]++;
}

Searching a random Array for a specific value

Hi I have been told to "Write code that determines if a value, say “5”, is contained in the array from task 7(a random array) by going backwards through the array starting at the end and comparing the search value with the values in the array. After the search, if the value is found print “The value has been found” otherwise print “The value has not been found”."
I understand the creation of the random array but I am stuck on how to work backwards through it and locate the specific value.
Here is the code so far
class Program
{
static void Main(string[] args)
{
int[] myArray = new int[10];
Random rand = new Random();
for (int i = 0; i < myArray.Length; i++)
{
myArray[i] = rand.Next(19);
}
}
}
}
Use the loop starting from largest to smallest index.
bool found = false;
for (int i = myArray.Length - 1; i >=0 ; i--)
if(myArray[i] == 5)
found = true;
if(found)
{
}
else
{
}
To go backward just use a for loop with the iterator to i--.
for (int i = myArray.Length - 1; i >= 0; i---)
{
if(// Check if myArray[i] equals the value to find)
{
// If it is the case, you can get out from the for loop with break
break;
}
}
The for loop is splitted in 4 parts:
for (initializer; condition; iterator)
body
The initializer is executed before the first iteration in the loop (here you want to start at the last index in the array : myArray.Length - 1)
The condition is evaluated for each iteration, if this condition is true then it goes to 3 (you want to stay in the for loop while i >= 0) otherwise it quit the for loop
The body is executed for each iteration that satisfy the condition
The iterator is executed (here as you want to go backward you want to decrease i)
Then it go back to 2

Find "not the same" elements in two arrays

I have two integer lists (List<int>). They contain the same elements, but List 1 contains elements that are not in the List 2.
How to find which elements of the List 1 ARE NOT in the List 2.
Thanks :)
PS. lang is c#
You can use IEnumerable.Except:
list1.Except(list2);
new HashSet<int>(l1).ExceptWith(l2);
A very easy solution:
HashSet<int> theSet1 = new HashSet<int>(List1);
theSet1.ExceptWith(List2);
For simplicity you can use the Contains method and check for one list not containing an element of the other:
for (int i = 0; i < list2.Count; ++i)
{
if (!list1.Contains(list2[i]) //current element is not in list 1
//some code
}
If your solution is that firs list contain second and to you hunting onli records added after first list ,
Maybe this is going to be useful
public static int DokleSuIsti(IList<string> prevzemNow, IList<string> prevzemOld)
{
int dobroja = 0;
int kolikohinaje;
if (prevzemOld.Count() < prevzemNow.Count())
{
kolikohinaje = prevzemOld.Count();
}
else
{
kolikohinaje = prevzemNow.Count();
}
for (int i = 0; i < kolikohinaje; i++)
{
if (!Object.Equals(prevzemNow[i], prevzemOld[i]))
{
dobroja = i;
return dobroja;
}
dobroja = i;
}
return dobroja;
}
After that you can use that int as starting point for walk trough your Ilist
If they are not sorted or something, you are going to have a hard time.
Either O(N^2) algorithm (a simple, stupid loop) or additional data structures, tell me which do you prefer.
Or, you can of course alter the source data by sorting, which I suppose is not an option.

Categories