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)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a List<int[]> that I populated by splitting an integer array into 4 groups. Now I need to get the difference of the two highest numbers in the array. I tried Array.Sort but I am stuck on how to continue.
What I have done so far?
public static void solution(int[] T)
{
List<int[]> splitted = new List<int[]>();//This list will contain all the splitted arrays.
int lengthToSplit = T.Length / 4;
int arrayLength = T.Length;
for (int i = 0; i < arrayLength; i = i + lengthToSplit)
{
int[] val = new int[lengthToSplit];
if (arrayLength < i + lengthToSplit)
{
lengthToSplit = arrayLength - i;
}
Array.Copy(T, i, val, 0, lengthToSplit);
splitted.Add(val);
}
//this is the part where I must get the difference between the two highest numbers in an integer array and put into another list.
foreach (int[] integerarray in splitted)
{
//get the difference of the two highest numbers per integer array and place it on another List<int>
}
}
get the difference between the two highest numbers in an integer array
and put into another list
You can use LINQ and Math.Abs:
List<int> differenceList = splitted
.Select(list => list.OrderByDescending(i => i).Take(2).ToArray())
.Select(highestTwo => Math.Abs(highestTwo[0] - highestTwo[1]))
.ToList();
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am writing the beginning of my program which is to have the computer generate 3 random numbers on the console.
They need to be 1-9 (including both), no numbers can repeat, and I need to put this answer into an array. What's needed in the main method class vs the class.
You should try it out yourself first (site rules say so), but some hints may be provided:
1) integer random numbers can be generated using Random class. More details can be found here and an answer has been already provided about generation
2) to avoid duplicates each number should be tested against the existing list of numbers:
array.Contains(generatedNumber)
3) For your particular request, an elegant option is to generate all numbers between 1 and 9, shuffle the array and pick the first three elements:
var initArray = Enumerable.Range(1, 9).ToArray();
var randomArray = initArray.OrderBy(x => rnd.Next()).ToArray();
Get first three elements and those are random and distinct.
Generally, you can a subarray using the method specified here.
Try this:
Random rnd = new Random();
int[] arr = Enumerable.Range(0, 10).OrderBy(n => rnd.Next()).Take(3).ToArray();
foreach (var n in arr)
{
Console.WriteLine(n);
}
Try this code below :
//range set 0 to 9
int Min = 0;
int Max = 10;
//declare an array which store 3 random number
int[] arr = new int[3];
Random randNum = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = randNum.Next(Min, Max);
Console.WriteLine(arr[i]);
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am reading in integer data from a spreadsheet that looks something like this:
40 50 60 70 80
I may be doing this all wrong (and that's why I am asking) but I am reading the data as a string and then splitting on the tab so I can create an array and access the elements to do further computation, but I end up having to convert back to an int (int x = Int32.Parse(next);) to do any operations. I know enough to know this whole thing seems very inefficient. Any suggestions to stream line things here a bit?
StreamReader stRead = new StreamReader(#"TestData.txt");
{
while (!stRead.EndOfStream)
{
listBox1.Items.Add(stRead.ReadLine());
}
string test = (string)listBox1.Items[5];
string[] words = test.Split('\t');
string next = words[2];
int x = Int32.Parse(next);
int y = x * x;
}
This might be better:
int y =
File
.ReadAllLines(#"TestData.txt")
.Skip(5)
.Select(x => int.Parse(x.Split('\t')[2]))
.Select(x => x * x)
.First();
But I suspect that you need it to be more robust. Do let us know what the actual data structure is.
I guess there is no real performance improvement that you could do, but you may be able to get rid of some unnecessary local variables.
Eg:
List<int> intList = ((string)listBox1.Items[5]).Split('\t').Select(Int32.Parse).ToList();
If you really don't need a ListBox, a DataTable is another option to handle such big amount of data. You could create required amount of columns with Int32 type.
DataTable dt = new DataTable();
var lines = File.ReadAllLines(pathToFile);
dt.Columns.AddRange(lines.First().Split('\t').Select(col => new DataColumn(){DataType = typeof(Int32)}).ToArray());
lines.Select(x => x.Split('\t')).ToList().ForEach(row => dt.Rows.Add(row));
Alternatively you could use ForEach, I have changed your initial code just to illustrate the concept
List<int> values = new List<int>();
str.Split('\t').ToList().ForEach(i =>
values.Add(Int32.Parse(i)));
You can use Select method with function parameter passed to it.
var str = "40\t50\t60\t70\t80";
var ints = str.Split('\t').ToList().Select(int.Parse);
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).
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am new to C# so please be gentle. I am using c# in a transformation script and I need to find the 6th highest value in a list such as this
57
50
90
60
57
93
100
53
73
87
77
I can change it into a string array by using
string [] arr = args.Content.Split("\r\n".ToCharArray());
but I get lost from there
Thanks
Paul Fone
If you want to sort it numerically you have to convert the strings to int first, then you can use Enumerable.OrderByDescending and Enumerable.Skip(5).Take(1):
IEnumerable<int> ints = arr.Select(int.Parse)
.OrderByDescending(i => i)
.Skip(5).Take(1);
Console.Write("Sixth element is: " + ints.First());
or create a new list from the ordered sequence at then use Enumerable.ElementAt:
List<int> ints = arr.Select(int.Parse).OrderByDescending(i => i).ToList();
Console.Write("Sixth element is: " + ints.ElementAt(5));
(omitted exception handling for invalid format or too little items)
You can use LINQ, like this:
var res = args.Content.Split("\r\n".ToCharArray())
.Select(int.Parse)
.OrderBy(x=>x)
.Skip(5)
.FirstOrDefault();
To start, you need to first convert your numbers into an int[]. You can do that like this:
string[] strs = args.Content.Split("\r\n".ToCharArray());
int[] ints = new int[strs.Length];
for (int i = 0; i < strs.Length; i++)
ints[i] = int.Parse(strs[i]);
Then you can use Array.Sort(ints); to actually sort them. Then, you use int result = ints[ints.Length - 6 - 1]; to get the sixth-to-last element in the sorted array: that is, the 6th highest element.
The completed code looks like this:
string[] strs = args.Content.Split("\r\n".ToCharArray());
int[] ints = new int[strs.Length];
for (int i = 0; i < strs.Length; i++)
ints[i] = int.Parse(strs[i]);
Array.Sort(ints);
int result = ints[ints.Length - 6 - 1];