Convert Ienumerable<int> to array and add to list C# - c#

I have a simple code:
List<int[]> list = new List<int[]>();
for (int i = 0; i < x; i++)
{
var vec = vector.Skip(index).Take(width);
var v = vec.ToArray();
list.Add(v);
index = index + width;
}
string toDisplay = string.Join(Environment.NewLine, list);
MessageBox.Show(toDisplay);
This is vector:
int[] vector = new int[length];
Random z = new Random();
for (int i = 0; i < length; i++)
{
vector[i] = z.Next(-100, 100);
}
What I want to do is to slice my vector on smaller vectors and add them to list of int. Using my code I only get System.Int32[] in MessageBox. I know that maybe my code it's not the right way. I barely know C#.
How can I do this in other way?

Apparently you mean to slice the initial array into smaller chunks and display them in a single line. This can be done using Linq as follows.
var StringToDisplay
= String.Join(Environment.NewLine, list.Select(iList => String.Join(",", iList)));

List<int[]> list is a list of arrays, not numbers. Calling ToString() on an array uses Object.ToString() which returns the object's (array's) type.
If you want to display a list of pages, you should change your string construction code to work with the inner arrays. One option is to use LINQ :
var lines=from page in list
select string.Join(",", page);
string toDisplay = string.Join(Environment.NewLine, lines);
It's better to use StringBuilder though, to avoid generating a lot of temporary strings:
var builder=new StringBuilder();
foreach(var page in list)
{
builder.AppendLine(string.Join(",", page));
}
string toDisplay = builder.ToString();
If you want a list of numbers change the list type to List. You can also simplify the code by using AddRange, eg :
List<int> list = new List<int>();
for (int i = 0; i < x; i++)
{
var vec = vector.Skip(index).Take(width);
list.AddRange(vec);
index = index + width;
}
string toDisplay = string.Join(Environment.NewLine, lines);

Related

Splitting a list c#

Hi I'm a little bit stuck in C#. I'm new on it.
This is my problem:
I have a list made up of 63 double numbers (let's call it "big list").
I want to split this list in 6 list with the following rule:
The first list consists of the first 8 elements of the big list;
The second list goes from the 9th element of the big list to the (9+8=17th) element of the big list;
The third list goes from the 18th element of the big list to the (18+8+1=27th) element of the big list;
The fourth list goes from the 28th element of the big list to the (28+8+2=38th) element of the big list;
The fifth list goes from the 39th element of the big list to the (39+8+3=50th) element of the big list;
The sixth list goes from the 51th element of the big list to the (51+8+4=63th) element of the big list;
How can I do it? thanks a lot in advance for your help!
i've tried in this way but it gives me error "cannot apply indexing with [] to an expression of type method group"
List listsplitted = new List();
for (int i = 0; i < 6; i++)
{
for (int j = 8; j < 8 + i + 1; j++)
{
Listsplitted[i] = biglist.Take[j];
}
}
It is a very simple approach with the IEnumerable extensions Skip and Take
List<double> first = bigList.Take(8).ToList();
List<double> second = bigList.Skip(8).Take(8).ToList();
List<double> third = bigList.Skip(16).Take(9).ToList();
List<double> fourth = bigList.Skip(25).Take(10).ToList();
List<double> fifth = bigList.Skip(35).Take(11).ToList();
// The last one is without Take to get every remaining element
List<double> sixth = bigList.Skip(46).ToList();
Of course you should check if the indexes are correct for your requirements. These indexes doesn't skip any elements from your bigList
You can make this approach more generic with something like this
void Main()
{
var bigList = GetYourBigList();
List<Tuple<int, int>> positions = new List<Tuple<int, int>>
{
new Tuple<int, int>(0,8),
new Tuple<int, int>(8,8),
new Tuple<int, int>(16,9),
new Tuple<int, int>(25,10),
new Tuple<int, int>(35,11),
new Tuple<int, int>(46,13)
};
List<List<int>> result = SplitTheList(bigList, positions);
foreach (var list in result)
{
foreach (var temp in list)
Console.WriteLine(temp);
Console.WriteLine("--------------------");
}
}
List<List<int>> SplitTheList(List<int> r, List<Tuple<int, int>> positions)
{
List<List<int>> result = new List<List<int>>();
foreach(var x in positions)
result.Add(r.Skip(x.Item1).Take(x.Item2).ToList());
return result;
}
You can do it using GetRange function:
List<double> part1= big_list.GetRange(0, 8);//Retrieves 8 items starting with index '0'
List<double> part2= big_list.GetRange(8, 9);//Retrieves 9 items starting with index '8'
Or if you don't want to give different names to all parts, you can create a list of lists:
List<List<double>> listoflists = new List<List<double>>();
listoflists.Add(big_list.GetRange(0, 8));//Retrieves 8 items starting with index '0'
listoflists.Add(big_list.GetRange(8, 9));//Retrieves 9 items starting with index '8'
for(int i=0; i<listoflists.Count;i++){
for(int j=0; j<listoflists[i].Count; j++){
Console.Write(listoflists[i][j] + " ");
}
Console.WriteLine();
}
if you are insisting on do the operation in one single for statement you can use the following code
const int arrSize = 6;
var splitedLists = new List<List<int>>(arrSize);
var defaultTake = 8;
var defaultSkip = 0;
for (var i = 1; i <= arrSize; i++)
{
if (i >= 3)
defaultSkip--;
splitedLists.Add(array.Skip(defaultSkip).Take(defaultTake + 1).ToList());
if (i >= 2)
defaultTake++;
defaultSkip = defaultSkip + defaultTake + 1;
}
If you can replace the list with an array, you can do without copying the data. You can use ArraySegment (or Span/Memory in newer versions of the language) to do this.
var array = Enumerable.Range(0, 63).Select(i => (double)i).ToArray();
var splitted = new List<ArraySegment<double>>();
int offset = 0;
int count = 8;
for (int i = 0; i < 6; i++)
{
splitted.Add(new ArraySegment<double>(array, offset, count));
offset += count;
count++;
}
// see what we have
foreach (var seg in splitted)
Console.WriteLine(seg.Offset + " " + seg.Count);
// work with segments
var segment = splitted[3];
segment[5] = 555555;
// the main array has also changed
Console.WriteLine(string.Join(" ", array));
Note that the segments do not store copies of the data, but refer to the data in the main array.

How to randomize the word that been get on the textfile

I want to ask if how can I randomize a word that I've get from the textfile data I made.
I already have the word actually from the textfile and stored into an array of character.
Here's what I have so far
I created a method called Shuffle
void Shuffle(string[] chArr)
{
//Shuffle
for (int i = 0; i < chArr.Length; i++)
{
string tmp = chArr[i].ToString();
int r = Random.Range(i, chArr.Length);
chArr[i] = chArr[r];
chArr[r] = tmp;
}
Debug.Log(chArr);
}
and use it like this
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string s = chArr.ToString();
string[] ss = new string[] { s };
Shuffle(ss);
foreach (char c in chArr)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
It still doesn't randomize that word I get from the textfile data.
EDITTED
So far here's what I did
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string charResult = "";
for(int i = 0; i < chArr.Length; i++)
{
int ran = Random.Range(0, chArr.Length);
charResult += chArr[ran];
}
Debug.Log(charResult);
foreach (char c in charResult)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
But instead of giving me for example the word "Abandon" it would give me sometimes a randomize word "aaaabn" could someone help me out why?
I will be using Fisher–Yates_shuffle
public static string Shuffle(string str)
{
System.Random random = new System.Random();
var array = str.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
int j = random.Next(i, array.Length);
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return String.Join("", array);
}
and to use it simply do
var f = "hello";
Console.WriteLine(Shuffle(f));
Your code is just getting random letters from that word but does not exclude duplicate. What you want instead is randomize the array of chars and convert it back to a string
System.Random rnd = new System.Random();
Char[] randomCharArray = chArr.OrderBy(x => rnd.Next()).ToArray();
string charResult = randomCharArray.ToString();
Unity has its own implementation of Random so be sure you use System.Random
it's most easier if you use a list (let call it initial list), (it may have some performance overheat do to shifts on remove, but i'm wonder if using a linked list would solve that...
Here what you can do if you do as i said:
Fill the list, with your words, or char, or any data which you want to randomize
Create another list or array to store randomized data in (result)
create a while loop, and check while, your initial list Has Item (count > 0)
use Random, and performe rand.Next(0, initialList.Count)
take the item within the index of random number and append it to the result list, (or replace free slot if you are using array)
List<string> initial = new List<string>();
initial.AddRange(data);
Random rand = new Random();
List<string> result = new List<string>();
while (initial.Count > 0) // LINQ: initial.Any()
{
int index = rand.Next(0, initial.Count);
result.Add(initial[index]);
initial.RemoveAt(index);
}
return result;

How to create a string set with multiple list?

User can pass any number of list with same number of elements in it. Example- user has passed below 3 (could be dynamic with same number of elements in it) list -
hospitalId - H11, H12, H13...n
patientId - P11, P12, P13...n
statusId - S11, S13, S11...n
What is the efficient way of creating a set out of it and storing it as a string in below format? Need a c# code for it.
expected output -
"((H11,P11, S11), (H12, P12, S13), (H13, P13, S11))"
You should iterate through your list and append them index wise to prepare the result.
StringBuilder builder = new StringBuilder();
builder.Append("(");
for(var index = 0; index < n; index++)
{
builder.AppendFormat("({0}, {1}, {2})", hospitalId[index], patientId[index], statusId[index]);
}
builder.Append(")");
var result = builder.ToString();
If you have n number of List<T> items with the same length, a basic loop will do the trick. Here's a version as an extension method that will take any number of lists as an input:
public static IEnumerable<IEnumerable<T>> ZipMultiple<T>(this List<List<T>> source)
{
var counts = source.Select(s => s.Count).Distinct();
if (counts.Count() != 1)
{
throw new ArgumentException("Lists aren't the same length");
}
for (var i = 0; i < counts.First(); i++)
{
var item = new List<T>();
for (var j = 0; j < source.Count; j++)
{
item.Add(source[j][i]);
}
yield return item;
}
}
After that, it's pretty simple to convert the result into a string in another loop, or you can do it as a single liner:
var zipped = lists.ZipMultiple();
var output = $"({string.Join(", ", zipped.Select(x => $"({string.Join(",", x)})"))})";

How to populate two separate arrays from one comma-delimited list?

I have a comma delimited text file that contains 20 digits separated by commas. These numbers represent earned points and possible points for ten different assignments. We're to use these to calculate a final score for the course.
Normally, I'd iterate through the numbers, creating two sums, divide and be done with it. However, our assignment dictates that we load the list of numbers into two arrays.
so this:
10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85
becomes this:
int[10] earned = {10,20,30,40,45,50,20,45,85};
int[10] possible = {10,20,35,50,50,50,20,90,85};
Right now, I'm using
for (x=0;x<10;x++)
{
earned[x] = scores[x*2]
poss [x] = scores[(x*2)+1]
}
which gives me the results I want, but seems excessively clunky.
Is there a better way?
The following should split each alternating item the list into the other two lists.
int[20] scores = {10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85};
int[10] earned;
int[10] possible;
int a = 0;
for(int x=0; x<10; x++)
{
earned[x] = scores[a++];
possible[x] = scores[a++];
}
You can use LINQ here:
var arrays = csv.Split(',')
.Select((v, index) => new {Value = int.Parse(v), Index = index})
.GroupBy(g => g.Index % 2,
g => g.Value,
(key, values) => values.ToArray())
.ToList();
and then
var earned = arrays[0];
var possible = arrays[1];
Get rid of the "magic" multiplications and illegible array index computations.
var earned = new List<int>();
var possible = new List<int>();
for (x=0; x<scores.Length; x += 2)
{
earned.Add(scores[x + 0]);
possible.Add(scores[x + 1]);
}
This has very little that would need a text comment. This is the gold standard for self-documenting code.
I initially thought the question was a C question because of all the incomprehensible indexing. It looked like pointer magic. It was too clever.
In my codebases I usually have an AsChunked extension available that splits a list into chunks of the given size.
var earned = new List<int>();
var possible = new List<int>();
foreach (var pair in scores.AsChunked(2)) {
earned.Add(pair[0]);
possible.Add(pair[1]);
}
Now the meaning of the code is apparent. The magic is gone.
Even shorter:
var pairs = scores.AsChunked(2);
var earned = pairs.Select(x => x[0]).ToArray();
var possible = pairs.Select(x => x[1]).ToArray();
I suppose you could do it like this:
int[] earned = new int[10];
int[] possible = new int[10];
int resultIndex = 0;
for (int i = 0; i < scores.Count; i = i + 2)
{
earned[resultIndex] = scores[i];
possible[resultIndex] = scores[i + 1];
resultIndex++;
}
You would have to be sure that an equal number of values are stored in scores.
I would leave your code as is. You are technically expressing very directly what your intent is, every 2nd element goes into each array.
The only way to improve that solution is to comment why you are multiplying. But I would expect someone to quickly recognize the trick, or easily reproduce what it is doing. Here is an excessive example of how to comment it. I wouldn't recommend using this directly.
for (x=0;x<10;x++)
{
//scores contains the elements inline one after the other
earned[x] = scores[x*2] //Get the even elements into earned
poss [x] = scores[(x*2)+1] //And the odd into poss
}
However if you really don't like the multiplication, you can track the scores index separately.
int i = 0;
for (int x = 0; x < 10; x++)
{
earned[x] = scores[i++];
poss [x] = scores[i++];
}
But I would probably prefer your version since it does not depend on the order of the operations.
var res = grades.Select((x, i) => new {x,i}).ToLookup(y=>y.i%2, y=>y.x)
int[] earned = res[0].ToArray();
int[] possible = res[1].ToArray();
This will group all grades into two buckets based on index, then you can just do ToArray if you need result in array form.
here is an example of my comment so you do not need to change the code regardless of the list size:
ArrayList Test = new ArrayList { "10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85" };
int[] earned = new int[Test.Count / 2];
int[] Score = new int[Test.Count / 2];
int Counter = 1; // start at one so earned is the first array entered in to
foreach (string TestRow in Test)
{
if (Counter % 2 != 0) // is the counter even
{
int nextNumber = 0;
for (int i = 0; i < Score.Length; i++) // this gets the posistion for the next array entry
{
if (String.IsNullOrEmpty(Convert.ToString(Score[i])))
{
nextNumber = i;
break;
}
}
Score[nextNumber] = Convert.ToInt32(TestRow);
}
else
{
int nextNumber = 0;
for (int i = 0; i < earned.Length; i++) // this gets the posistion for the next array entry
{
if (String.IsNullOrEmpty(Convert.ToString(earned[i])))
{
nextNumber = i;
break;
}
}
earned[nextNumber] = Convert.ToInt32(TestRow);
}
Counter++
}

Defining Dynamic Array

How can I define a dynamic array in C#?
C# doesn't provide dynamic arrays. Instead, it offers List class which works the same way.
To use lists, write at the top of your file:
using System.Collections.Generic;
And where you want to make use of a list, write (example for strings):
List<string> mylist = new List<string>();
mylist.Add("First string in list");
Take a look at Array.Resize if you need to resize an array.
// Create and initialize a new string array.
String[] myArr = {"The", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "dog"};
// Resize the array to a bigger size (five elements larger).
Array.Resize(ref myArr, myArr.Length + 5);
// Resize the array to a smaller size (four elements).
Array.Resize(ref myArr, 4);
Alternatively you could use the List class as others have mentioned. Make sure you specify an initial size if you know it ahead of time to keep the list from having to resize itself underneath. See the remarks section of the initial size link.
List<string> dinosaurs = new List<string>(4);
Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
dinosaurs.Add("Tyrannosaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Deinonychus");
If you need the array from the List, you can use the ToArray() function on the list.
string[] dinos = dinosaurs.ToArray();
C# does provide dynamic arrays and dynamic array manipulation. The base of an array is dynamic and can be modified with a variable. You can find the array tutorial here (https://msdn.microsoft.com/en-us/library/aa288453%28v=vs.71%29.aspx). I have also included code that demonstrates an empty set array and a dynamic array that can be resized at run time.
class Program
{
static void Main(string[] args)
{
int x = Convert.ToInt32(Console.ReadLine());
int y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(x);
{
int[] dynamicArray1 = { };//empty array
int[] numbers;//another way to declare a variable array as all arrays start as variable size
numbers = new int[x];//setting this array to an unknown variable (will be user input)
for (int tmpInt = 0; tmpInt < x; tmpInt++)//build up the first variable array (numbers)
{
numbers[tmpInt] = tmpInt;
}
Array.Resize(ref numbers,y);// resize to variable input
dynamicArray1 = numbers;//set the empty set array to the numbers array size
for (int z = 0; z < y; z++)//print to the new resize
{
Console.WriteLine(numbers[z].ToString());//print the numbers value
Console.WriteLine(dynamicArray1[z].ToString());//print the empty set value
}
}
Console.Write("Dynamic Arrays ");
var name = Console.ReadLine();
}
}
Actually you can have Dynamic Arrays in C# it's very simple.
keep in mind that the response to your question above is also correct you could declare a
List Generic
The way to Create a Dynamic Array would be to declare your Array for example
string[] dynamicArry1 = { };//notice I did not declare a size for the array
List<String> tmpList = new List<string>();
int i = 1;
for(int tmpInt = 0; tmpInt < 5; tmpInt++)
{
tmpList.Add("Testing, 1.0." + tmpInt + ", 200, 3.4" + tmpInt +"," + DateTime.Now.ToShortDateString());
//dynamicArry1[tmpInt] = new string[] { tmpList[tmpInt].ToCharArray() };
}
dynamicArry1 = tmpList.ToArray();
how about ArrayList ?
If I'm not wrong ArrayList is an implementation of dynamic arrays
Example of Defining Dynamic Array in C#:
Console.WriteLine("Define Array Size? ");
int number = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter numbers:\n");
int[] arr = new int[number];
for (int i = 0; i < number; i++)
{
arr[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < arr.Length; i++ )
{
Console.WriteLine("Array Index: "+i + " AND Array Item: " + arr[i].ToString());
}
Console.ReadKey();
like so
int nSize = 17;
int[] arrn = new int[nSize];
nSize++;
arrn = new int[nSize];

Categories