Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Let's assume I have a list and want to run a method only one time if the program enters the foreach. But important thing is initially I don't know if the loop empty or not.
What is the best practice to run a code snippet only one time inside foreach loop?
List<int> dummy = new List<int> {1, 2, 3, 4, 5};
int sum = 0;
foreach (int i in dummy)
{
sum += i;
DoJob(); //this method must run only once
}
I tried this but it did not look well
List<int> dummy = new List<int> {1, 2, 3, 4, 5};
int sum = 0;
foreach (int i in dummy)
sum += i;
if (dummy.Count>0)
DoJob();
Do you have any better idea?
Does it have to be inside the loop? From what you've posted, it doesn't seem to.
List<int> dummy = new List<int> {1, 2, 3, 4, 5};
if(dummy.Any())
DoJob();
int sum = 0;
foreach (int i in dummy)
sum += i;
Also, I'm assuming that snippet is just an example and not your actual code... if it is your actual code, you can use Sum (e.g., int sum = dummy.Sum();) instead of a foreach loop.
I'm also assuming your actual code uses an actual List<T> or some other concrete collection type. If it uses an IEnumerable, then the code above will iterate through the enumerable twice, which isn't recommended. If the enumerable actually represents a database query, you'll hit the database twice. So, if that's the case, just materialize the enumerable by calling .ToList first.
If using linq
if (dummy != null && dummy.Any())
{
DoJob();
}
If not using linq
if (dummy != null && dummy.Count > 0)
{
DoJob();
}
C# specification clearly states purpose of foreach statement (8.8.4 The foreach statement):
foreach (type identifier in expression) embedded-statement
The foreach statement enumerates the elements of a collection,
executing an embedded statement for each element of the collection.
So, if you want something to be executed for each element of the collection, then put it in the embedded statement. If you want something to be executed only once, then putting it in a statement which executes for each element of the collection, and trying to avoid running it for each element - not very good idea.
Your last sample looks completely OK to me. Just remove braces (matter of taste though).
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
So I tried to return my array with a foreach loop... but no results... If someone can help me return an array, it will help me greatly.
Here is the test code of how I tried to do that:
int[] ints = { 1, 2, 3 };
foreach(int i in ints)
{
return ints[i];
}
The code in the question shows how javascript handles foreach loops. In javascript, the foreach loop iterates over the indexes. C# is different. In C#, the foreach loop iterates over the values. Therefore you want this:
int[] ints = { 4, 5, 6 };
foreach(int i in ints)
{
return i;
}
Additionally, this code will exit the method as soon as it hits the return keyword for the first time and only provide the first value. If you want to return an array, you can just... return the array:
int[] ints = { 4, 5, 6 };
return ints;
Like #lee Taylor mentioned. It is weird to do this, but yield is what you want.
int[] ints = { 1, 2, 3 };
foreach(int i in ints)
{
yield return i;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to compare every value of one list against every value of another list and then remove any matching values and currently have this code.
foreach (item s in List1)
{
for (int i = 0; i < list2.count; i++)
{
if (list2.ElementAt(i)==s)
{
list2.Remove(list2.ElementAt(i));
continue;
}
}
}
There has to be a faster or at the very least, a less intensive method of performing a comparison like this. A faster method is required as this could be used to compare lists which exceed 1000 values each. Any help would be much apreciated
Use Except, it produces difference of two sequences by using the default equality comparer.
Except extension method uses a HashSet<T> which produces O(1) access in LookUp.
list2 = list2.Except(list1).ToList();
You want to remove all elements from list2 that are contained in list1. An efficient way would be to create a HashSet that will contain a reference to every object in list1, because lookups against a HashSet are very fast. Then iterate over each element in list2, but in reverse order. This is important because you'll be removing elements. Try something like this:
List<MyObjType> list1 = new List<MyObjType>();
List<MyObjType> list2 = new List<MyObjType>();
HashSet<MyObjType> list1Hashset = new HashSet<MyObjType>(list1);
for (int i = list2.Count - 1; i >= 0; i--)
{
if (list1Hashset.Contains(list2[i]))
list2.RemoveAt(i);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have list of Strings, sometimes over 10.000.000 strings in the list.
I need to loop through the list and send chunks of this data to an API, a sublist of 2k strings per API-call.
What would be the most efficient way to do this?
Use LINQ Take and Skip operator wisely with variables.
For example syntax will be something like below-
IEnumerable<resultStrings> page1 = myStrings.Skip(0).Take(2000);
IEnumerable<resultStrings> page2 = myStrings.Skip(2000).Take(2000);
Try GetRange method:
List<int> list = new List<int>() { 1, 2, 3, 4, 5};
var chunk = 2;
var iterations = list.Count / chunk;
for (int i = 0; i < iterations; i++)
{
var portion = list.GetRange(chunk * i, chunk);
//Do API
}
var remainder = list.GetRange(chunk * iterations, list.Count - chunk * iterations);
//Do API
You can look at some benchmark test on GetRange vs Take where GetRange wins.
https://icodeit.wordpress.com/2012/08/27/performance-of-skip-and-take-in-linq-to-objects/
Probably the most efficient approach is to use a database instead of loading all into memory(from wherever) and then use Skip/Take to take parts of it.
However, you could use GroupBy:
var chunks = largeStringList.Select((str, index) => new { str, index })
.GroupBy(x => x.index / 2000, x => x.str);
foreach (var chunkGroup in chunks)
Console.WriteLine(String.Join(",", chunkGroup));
I've run a little performance test with this result:
List.GetRange:
00:00:00.0404119 (40 milliseconds)
(my) GroupBy:
00:00:02.2386504 (two seconds)
Skip/Take:
00:10:11.6467726 (yes, more than 10 minutes)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an array and am trying to extract the vlaues. I have tried to find the length of the array, but as the array isnt always full the .length doesnt work for me. How do i work out how many values are stored in the array?
Heres the code;
int length = numbers.Length;
I have created the array in the main section of the code, I am trying to make a function that can get the values out of the code using a for loop. E.G
int number(i) = numbers[i]
so that the variable number[i] will become number0, and then assigned the value in the first row of the array
If you want to use array which is not always full, then you definitely should use List<T> instead of array, because list can contain variable number of items. With array you never can tell if default value (zero for integer) was assigned to array item, or item was not assigned at all. Getting list items count will look like list.Count.
Of course, you can get number of array items which have non-default value (but see above why it might be not good approach):
int[] array = { 1, 2, 0, 1, 5 };
int count = array.Count(i => i != default(int)); // 4
try foreach you do not need the length. Here is code:
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
foreach (int element in numbers)
{
System.Console.WriteLine(element);
}
I have a rather specific question about how to exclude items of one list from another. Common approaches such as Except() won't do and here is why:
If the duplicate within a list has an "even" index - I need to remove THIS element and the NEXT element AFTER it.
if the duplicate within a list had an "odd" index - I need to remove THIS element AND one element BEFORE** it.
there might be many appearances of the same duplicate within a list. i.e. one might be with an "odd" index, another - "even".
I'm not asking for a solution since I've created one myself. However after performing this method many times - "ANTS performance profiler" shows that the method elapses 75% of whole execution time (30 seconds out of 40). The question is: Is there a faster method to perform the same operation? I've tried to optimize my current code but it still lacks performance. Here it is:
private void removedoubles(List<int> exclude, List<int> listcopy)
{
for (int j = 0; j < exclude.Count(); j++)
{
for (int i = 0; i < listcopy.Count(); i++)
{
if (listcopy[i] == exclude[j])
{
if (i % 2 == 0) // even
{
//listcopy.RemoveRange(i, i + 1);
listcopy.RemoveAt(i);
listcopy.RemoveAt(i);
i = i - 1;
}
else //odd
{
//listcopy.RemoveRange(i - 1, i);
listcopy.RemoveAt(i - 1);
listcopy.RemoveAt(i - 1);
i = i - 2;
}
}
}
}
}
where:
exclude - list that contains Duplicates only. This list might contain up to 30 elements.
listcopy - list that should be checked for duplicates. If duplicate from "exclude" is found -> perform removing operation. This list might contain up to 2000 elements.
I think that the LINQ might be some help but I don't understand its syntax well.
A faster way (O(n)) would be to do the following:
go through the exclude list and make it into a HashSet (O(n))
in the checks, check if the element being tested is in the set (again O(n)), since test for presence in a HashSet is O(1).
Maybe you can even change your algorithms so that the exclude collection will be a HashSet from the very beginning, this way you can omit step 1 and gain even more speed.
(Your current way is O(n^2).)
Edit:
Another idea is the following: you are perhaps creating a copy of some list and make this method modify it? (Guess based on the parameter name.) Then, you can change it to the following: you pass the original array to the method, and make the method allocate new array and return it (your method signature should be than something like private List<int> getWithoutDoubles(HashSet<int> exclude, List<int> original)).
Edit:
It could be even faster if you would reorganize the input data in the following way: As the items are always removed in pairs (even index + the following odd index), you should pair them in advance! So that your list if ints becomes list of pairs of ints. This way your method might be be something like that:
private List<Tuple<int, int>> getWithoutDoubles(
HashSet<int> exclude, List<Tuple<int, int>> original)
{
return original.Where(xy => (!exclude.Contains(xy.Item1) &&
!exclude.Contains(xy.Item2)))
.ToList();
}
(you remove the pairs where either the first or the second item is in the exclude collection). Instead of Tuple, perhaps you can pack the items into your custom type.
Here is yet another way to get the results.
var a = new List<int> {1, 2, 3, 4, 5};
var b = new List<int> {1, 2, 3};
var c = (from i in a let found = b.Any(j => j == i) where !found select i).ToList();
c will contain 4,5
Reverse your loops so they start at .Count - 1 and go to 0, so you don't have to change i in one of the cases and Count is only evaluated once per collection.
Can you convert the List to LinkedList and have a try? The List.RemoveAt() is more expensive than LinkedList.Remove().