My problem today is about creating an array from an existing one.
My "parent" array contains elements with two characters.
My new array's elements should contain 20 elements from the "parent" array.
Example:
string[] parentArray = {aa, bb, cc, df, ds, aa, zz, xx, cc, ww, fg, qq, ww, ee,
key: (0) (1) (2) (3) (4) (6) (7) (8) (9) (10)........ rr, dd, ss, qq, dd, ss, sa, wq, ee, rr}
string[] childArray = {aabbccdfdsaazzxxccwwfgqqwweerrddssqqddss,.....}
(1)
With some of the extension functions for enumerables you can go a long way here.
int cursor = 0;
List<string> result = new List<string>();
while (cursor < parentArray.Length)
{
result.Add(String.Join("", parentArray.Skip(cursor).Take(20)));
cursor += 20;
}
string[] childArray = result.ToArray();
This function walks over your array, fetches 20 elements (or less in case there aren't 20 elements left) and merges them into a string and add that string to a list. I made use of the String.Join method to concat the string. That works nicely here.
The Skip function and the Take function are extension functions for IEnumerable and do just what they say.
EDIT: I did assume that your source array is longer and may contain multiple blocks of 20 elements that need to be moved to the childArray
EDIT2: In case you have a load of values in your parentArray you may want to go a different way, to get some more performance out of it. In that case I suggest using the StringBuilder.
var builder = new Text.StringBuilder();
List<string> result = new List<string>();
for (int cursor = 0; cursor < parentArray.Length; cursor++)
{
if (builder.Length > 0 && (cursor % 20) == 0)
{
result.Add(builder.ToString());
builder.Length = 0;
}
builder.Append(parentArray[cursor]);
}
/* At this point you can choose to add the remaining elements to the list or not. */
if (builder.Length > 0)
{
result.Add(builder.ToString());
}
string[] childArray = result.ToArray();
Sounds as if a simple LINQ-statement will do what you need:
var myArr = parent.Take(20).ToArray();
This will select the 20 first elements of your parent-array.
EDIT: To do this with all of your elements within parent loop its entries:
List<string> result= new List<string>();
while(parent.Any()) {
result.Add(String.Join("", parent.Take(20).ToArray());
parent = parent.Skip(20).ToArray();
}
Finally convert your list back to an array using result.ToArray.
You can make a for loop on the parent array and add the element inside the array to a string like the following
String str="";
for (int i=0;i<count(parent);i++){
str+=parent[i].tostring();
}
Then make a new string array and at the first index put the str variable...
Hope this help you if this what u r asking for.
Related
I want to trim all the white-spaces and empty strings only from the starting and ending of an array without converting it into a string in C#.
This is what I've done so far to solve my problem but I'm looking for a bit more efficient solution as I don't want to be stuck with a just works solution to the prob
static public string[] Trim(string[] arr)
{
List<string> TrimmedArray = new List<string>(arr);
foreach (string i in TrimmedArray.ToArray())
{
if (String.IsEmpty(i)) TrimmedArray.RemoveAt(TrimmedArray.IndexOf(i));
else break;
}
foreach (string i in TrimmedArray.ToArray().Reverse())
{
if (String.IsEmpty(i)) TrimmedArray.RemoveAt(TrimmedArray.IndexOf(i));
else break;
}
return TrimmedArray.ToArray();
}
NOTE: String.IsEmpty is a custom function which check whether a string was NULL, Empty or just a White-Space.
Your code allocates a lot of new arrays unnecessarily. When you instantiate a list from an array, the list creates a new backing array to store the items, and every time you call ToArray() on the resulting list, you're also allocating yet another copy.
The second problem is with TrimmedArray.RemoveAt(TrimmedArray.IndexOf(i)) - if the array contains multiple copies of the same string value in the middle as at the end, you might end up removing strings from the middle.
My advice would be split the problem into two distinct steps:
Find both boundary indices (the first and last non-empty strings in the array)
Copy only the relevant middle-section to a new array.
To locate the boundary indices you can use Array.FindIndex() and Array.FindLastIndex():
static public string[] Trim(string[] arr)
{
if(arr == null || arr.Length == 0)
// no need to search through nothing
return Array.Empty<string>();
// define predicate to test for non-empty strings
Predicate<string> IsNotEmpty = string s => !String.IsEmpty(str);
var firstIndex = Array.FindIndex(arr, IsNotEmpty);
if(firstIndex < 0)
// nothing to return if it's all whitespace anyway
return Array.Empty<string>();
var lastIndex = Array.FindLastIndex(arr, IsNotEmpty);
// calculate size of the relevant middle-section from the indices
var newArraySize = lastIndex - firstIndex + 1;
// create new array and copy items to it
var results = new string[newArraySize];
Array.Copy(arr, firstIndex, results, 0, newArraySize);
return results;
}
I like the answer by Mathias R. Jessen as it is efficient and clean.
Just thought I'd show how to do it using the List<> as in your original attempt:
static public string[] Trim(string[] arr)
{
List<string> TrimmedArray = new List<string>(arr);
while (TrimmedArray.Count>0 && String.IsEmpty(TrimmedArray[0]))
{
TrimmedArray.RemoveAt(0);
}
while (TrimmedArray.Count>0 && String.IsEmpty(TrimmedArray[TrimmedArray.Count - 1]))
{
TrimmedArray.RemoveAt(TrimmedArray.Count - 1);
}
return TrimmedArray.ToArray();
}
This is not as efficient as the other answer since the internal array within the List<> has to shift all its elements to the left each time an element is deleted from the front.
Hey guys Im trying to be able to save an array from a text file but I'm at my wits end trying to figure out how to save it. I can print all the elements of the matrix as can be seen from the text file.
Sample input:
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
1 2 3 4 5
I keep getting an index out of range exception. Not sure what's happening.
Hopefully you guys understand what im trying to do.
Here's what I have so far:
class Program
{
static void Main(string[] args)
{
string input =
#"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 5\Chapter 15 Question 5\TextFile1.txt";
StreamReader reader = new StreamReader(input);
List<string> list = new List<string>();
char[] unwanted = new char[] { ' ' };
using (reader)
{
int row = 0;
int column = 0;
string line = reader.ReadLine();
while (line != null)
{
string[] numbersString = line.Split(unwanted);
int[,] numbersInt = new int [ row, numbersString.Length];
foreach (string a in numbersString)
{
Console.Write("{0} ",a);// this is to check that the array was read in the right order
numbersInt[row, column] = int.Parse(a);
column++;
}
line = reader.ReadLine();
Console.WriteLine();
row++;
}
}
}
}
I suggest using jugged arrays (array of array int[][]) instead of 2D ones; in that case the solution will be quite simple, something like this (Linq):
int[][] matrix = File
.ReadLines(#"C:\myFile.txt")
.Split(new Char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries)
.Select(items => items
.Select(item => int.Parse(item))
.ToArray())
.ToArray();
Test (let's print out the matrix):
String report = String.Join(Environment.NewLine, matrix
.Select(line => String.Join(" ", line)));
Console.Write(report);
This change in your while should do the trick:
while (line = file.ReadLine()) != null)
{
...
}
Source: MSDN
You appear to be creating your instance of numbersInt inside your while loop. This means that with each pass of the loop you will re-create the array and when the loop exits the array will be lost. Move the declaration for numberInt to outside of the while loop.
Your immediate issue is that your code does not reset column back to zero after reading each line. Move int column = 0 into the while loop to fix this issue.
The second issue is numbersInt allocation. You create it for each line, which is not right, because it's a 2-D array. You need to create it before the loop, but of course you can't, because you don't know how many lines you are going to have. One approach is to use a dynamic data structure, and add one row at a time to it.
You can greatly simplify your code by using File.ReadAllLines method in combination with LINQ, because this would let you get rid of a lot of simple code. Now you can check how many lines you have before creating your 2-D array, and you could fill it in much easier as well:
var allRows = File
.ReadLines(#"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 5\Chapter 15 Question 5\TextFile1.txt")
.Select(line => line.Split(unwanted).Select(int.Parse).ToList())
.ToList();
If you are OK with an array of arrays, you don't need to do anything: allRows is a 2-D structure of rows and columns containing your matrix.
If you must convert it to a 2-D array, you can do it with a pair of nested for loops:
if (allRows.Count == 0) {
// ... The file has no data - handle this error
}
var matrix = new int[allRows.Count, allRows[0].Count];
for (int row = 0 ; row != allRows.Count ; row++) {
for (int col = 0 ; col != allRows[0].Count ;col++) {
matrix[row, col] = allRows[row][col];
}
}
I've made a program that extracts some info from a file , do some operations with it and store it back on a list.
Following this link:
Are 2 dimensional Lists possible in c#?
I've been able to create a class with a list who would suit my needs. But after some debugging i've found that i was overwriting the list on each loop iteration.
Then i decided to make an array of lists - followed this link:
How to create an array of List<int> in C#?
Created an array of lists, initialized it and added elements. But when it needs to move to the next list position , it throws the out of boundaries exception.
I've tried a few things (readed about race condition) but none of 'em worked.
The problem will happen only when i open more than one file with my code ; otherwise it works perfectly.
Exception is thrown at xmldata , in the last iteration of the current file.
Ex: Selected two files, each one will add five elements. In the last element of the first file the exception will be thrown and there's data in the last element's position to be added.
Additional information: Index was outside the bounds of the array. (Exception thrown).
Any help will be appreciated. Thanks a lot.
Code:
List<xmldata>[] finalcontent = new List<xmldata>[9999];
finalcontent[listpos] = new List<xmldata>();//Initializing a list for each filename
foreach (Match m in matches)
{
Double[] numbers;
string aux;
aux = m.Groups[1].ToString();
aux = Regex.Replace(aux, #"\s+", "|");
string[] numbers_str = aux.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
numbers = new Double[numbers_str.Length];
for (int j = 0; j < numbers.Length; j++)
{
numbers[j] = Double.Parse(numbers_str[j], CultureInfo.InvariantCulture);
//Converts each number on the string to a Double number, store it in a position
//in the Double array
numbers[j] = numbers[j] / 100; //Needed calculus
numbers[j] = Math.Round(numbers[j], 3); //Storing numbers rounded
}
string values = String.Join(" ", numbers.Select(f => f.ToString()));
if (i <= colors_str.Length)
{
finalcontent[listpos].Add(new xmldata//The exception is thrown right here
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
}//Closing if
i++;
}//Closing foreach loop
Link to the file: https://drive.google.com/file/d/0BwU9_GrFRYrTT0ZTS2dRMUhIWms/view?usp=sharing
Arrays are fixed size, but Lists automatically resize as new items are added.
So instead, and since you're using Lists anyway, why not use a list of lists?
List<List<int>> ListOfListsOfInt = new List<List<int>>();
Then, if you really absolutely must have an array, then you can get one like this:
ListOfListsOfString.ToArray();
// Convert non-ascii characters to .
for (int jx = 0; jx < cnt; ++jx)
if (line[jx] < 0x20 || line[jx] > 0x7f) line[jx] = (byte)'.';
This is a big example, but check this one. You increase 'jx' before entering the statement, possibly exceeding the boundary of cnt?
Try changing the following:
if (i <= colors_str.Length)
to
if (i < colors_str.Length).
In fact I'm convinced that this is the problem.
This is because refereces begin at 0 and the last reference is length - 1, not length.
When using a list - it is better to use native functions for it.
List<xmldata>[] finalcontent = new List<xmldata>();
......
finalcontent[listpos] = new List<xmldata>(); insted of var _tmpVariable = new List<xmldata>();//Initializing a list for each filename
......
_tmpVariable.Add(new xmldata
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
fs.Close();//closing current file
listpos++;//Increment list position counter
finalcontent.Add(_tmpVariable); // add list into list
As there is no exception details it is hard to get where the exception is thrown.
It could be a list issue, a string issue or other (even file reading issue as well),
So please update this with current exception details.
I have a file containing scores in the following format:
000001,1
000002,2
000012,1
232124,1
I build an array containing the score as the first element and the difficulty as the second element. I then add the array to the list like this:
// load highscores
public void LoadScores()
{
StreamReader file = new StreamReader("highScores.txt");
// loop through each line in the file
while ((line = file.ReadLine()) != null)
{
// seperate the score from the difficulty
lineData = line.Split(',');
// add each line to the list
list.Add(lineData);
}
OrderScores();
}
Next I order the list using an IEnumerable:
IEnumerable<string[]> scoresDesNormal, scoresDesHard;
// order the list of highscores
protected void OrderScores()
{
// order the list by descending order with normal difficulty at the top
scoresDesNormal = list.OrderByDescending(ld => lineData[0]).Where(ld => lineData[1].Contains("1"));
// order the list by descending order with hard difficulty at the top
scoresDesHard = list.OrderByDescending(ld => lineData[0]).Where(ld => lineData[1].Contains("2")).Take(3);
}
Now I want to print the two IEnumerable lists to the screen using spriteBatch.DrawString(). How do I correctly iterate through the list elements and the arrays in side of them? I want to print out both elements of each array stored in the lists.
First of all, your question.
If you do know how to draw 1 string, and you want to draw 2 strings combined with a separator between them ",", simply do this:
...
string firstString = ...
string secondString = ...
string toBeDrawn = firstString + "," + secondString;
DrawThisFellah ( toBeDrawn );
...
So, you have a string[] ? No problem:
...
string[] currentElement = ...
string firstString = currentElement[0];
string secondString = currentElement[1];
// etc
...
Secondly, you don't need to add the leading zeros just for the alphabetical OrderByDescending to work. You could parse (and thus validate) the strings and store them in elements of type int[] instead of string[].
THIRD, and this might interest you !
It is dangerous to use LINQ without knowing you're using it.
Are you aware that your IEnumerable<string[]> are actually queries, right ?
One could say that your IEnumerable<string[]> objects are actually "CODE AS DATA".
They contain not the result for your OrderByDescending but rather the logic itself.
That means that if you have say, 3 string[] elements in your lineData:
{ "1", "122" }, { "3", "42" }, { "5", "162" }
and you call OrderScores, then you will notice the results when enumerating scoresDesNormal (for instance). The following code:
foreach (var element in scoresDesNormal)
Console.WriteLine("{0}, {1}", element[0], element[1]);
would print out to the console:
1, 122
5, 162
(because the 2nd element has no '1' characters on the second subelement)
but if you go on and modify the lineData collection either by inserting new elements or removing elements (should it be a List<string[]>) or simply by modifying the values of existing elements (should it be a primitive array), then you will observe new results when enumerating scoresDesNormal without calling OrderScores !
So for instance the following code's comments are true (given you have a List<string[]> lineData):
List<string[]> lineData = new List<string[]>(new[] {
new[] { "1", "122" }, // contains 1
new[] { "3", "42" }, // does not contain 1
new[] { "5", "162" } // contains 1
});
OrderScores();
foreach (var element in scoresDesNormal)
Console.WriteLine(element[1]);
// the previous foreach prints out
// 162
// 122
lineData[1][1] = "421"; // make the "42" in the list become "421"
foreach (var element in scoresDesNormal)
Console.WriteLine(element[1]);
// the previous foreach prints out - even though we haven't called OrderScores again
// 162
// 421
// 122
If i were you, i would do it like this,
If the user clicks or presses a button to view scores, open a method, like this one.
public void DisplayScores()
{
Rectangle[] PositionOfText = new Rectangle[scoresDesNormal];
for (int i = 0; i< scoresDesNormal.Count; i++)
{
PositionOfText = new Rectangle(xPos, yPos, Width, Height);
}
//do the same for the other difficulties, this sets the position of the texts.
import a fontbatch that you would like to use.
and in your draw method have something like this,
for (int i = 0; i< scoresDesNormal.Count; i++)
spritebatch.drawString(MyFontBatch, scoresDesNormal[i], PositionOfText, Color.//your preffered color.
Now i can understand that their may be errors in that, but i'm not a fluent c# programmer, But thats more or less what you can do
I have this assignment where I must delete a chosen element from an array, so I came up with this code:
strInput = Console.ReadLine();
for (int i = 0; i < intAmount; i++)
{
if (strItems[i] == strInput)
{
strItems[i] = null;
for (int x = 0; x < intAmount-i; x++)
{
i = i + 1;
strItems[i - 1] = strItems[i];
}
intAmount = intAmount - 1;
}
}
The problem is that, suppose I have an array [1,2,3,4,5,], and I want to delete 1. The output would be [2,3,4,5,5]. This also happens when I choose 2, but it does not happen when I choose any other number.
What am I doing wrong?
I'm assuming you are working with a basic array of strings:
var strItems = new string[] { "1", "2", "3", "4", "5" };
In .NET, that array is always going to be 5 elements long. In order to remove an element, you are going to have to copy the remaining elements to a new array and return it. Setting the value at a position to null does not remove it from the array.
Now, with things like LINQ this is very easy (not shown here), or you could cheat using the List<> collection and do this:
var list = new List<string>(strItems);
list.Remove("3");
strItems = list.ToArray();
But I don't think that's going to teach you anything.
The first step is to find the index of the element you wish to remove. You can use Array.IndexOf to help you out. Let's find the middle element, "3":
int removeIndex = Array.IndexOf(strItems, "3");
If the element was not found, it will return a -1, so check for that before doing anything.
if (removeIndex >= 0)
{
// continue...
}
Finally you have to copy the elements (except the one at the index we don't want) to a new array. So, altogether, you end up with something like this (commented for explanation):
string strInput = Console.ReadLine();
string[] strItems = new string[] { "1", "2", "3", "4", "5" };
int removeIndex = Array.IndexOf(strItems, strInput);
if (removeIndex >= 0)
{
// declare and define a new array one element shorter than the old array
string[] newStrItems = new string[strItems.Length - 1];
// loop from 0 to the length of the new array, with i being the position
// in the new array, and j being the position in the old array
for (int i = 0, j = 0; i < newStrItems.Length; i++, j++)
{
// if the index equals the one we want to remove, bump
// j up by one to "skip" the value in the original array
if (i == removeIndex)
{
j++;
}
// assign the good element from the original array to the
// new array at the appropriate position
newStrItems[i] = strItems[j];
}
// overwrite the old array with the new one
strItems = newStrItems;
}
And now strItems will be the new array, minus the value specified for removal.
Arrays in C# are of a fixed size - once initialized you can only modify items, but you cannot add or remove items. If you want to delete an item from a collection you have two options:
1.) Create a new array that has all members of the original array minus the one you want to remove.
2.) Use a collection type that is resizable and allows to add or remove items like List<T> (List<int> in your case). This is what you would do in the "real world" if your collection is not static.
In your specific implementation i think u miss a break; statement, you should go out from the outer loop when you finish the inner loop. The assignment to null is not useful at all.
If the list is just a list of numbers why are you using strings? use integers directly if it is the case.
Your exercise seems to ask something like this, if you need to remove only one element.
public bool MyDelete(int[] array, int value) // Easy to do for strings too.
{
bool found = false;
for (int i = 0; i < array.Length; ++i)
{
if (found)
{
array[i - 1] = array[i];
}
else if (array[i] == value)
{
found = true;
}
}
return found;
}
This function will returns true if it find the specified falue, false if not.
It will move all items as you describe in your example, but of course, it will not change the size of the array.
Arrays are fixed size.
You cannot change the size of an array, simply, the language don't allows that.
Arrays are, were and will be always fixed size!
To remove an item from an array you should do something this:
public static T[] RemoveAt<T>(T[] array, int index) // hope there are not bugs, wrote by scratch.
{
int count = array.Length - 1;
T[] result = new T[count];
if (index > 0)
Array.Copy(array, 0, result, 0, index - 1);
if (index < size)
Array.Copy(array, index + 1, result, index, size - index);
return result;
}
...
strItems = RemoveAt(strItems, index);
This function will create a new array that contains all elements except the one at the index you specify.
Now, why someone would do something like this instead of using a List or a Dictionary or wathever?
Use directly a List without using an array.
Can use Except method to filter the data
AllData = {10, 30, 20, 50}
FilterData = {30, 20}
Result = AllData.Except(​FilterData)
Result will be {10, 50}
Arrays are a fixed sized, you can't shorten their length without creating a new array. All you can do is store the length of valid elements in the array (ie. after you remove 1 the length is 4).
Also, I'm not sure if the order of elements in your array is important, but if it's not you could swap the first and last elements rather than moving every element after the one that's removed forward 1 position.
An alternative to using an array is using a collection such as an ArrayList which will take care of resizing, removing and keeping a count of the amount of items in it, plus a lot more.
However, since this is homework you might have to use arrays. Either keep track of the length with a variable, as opposed to using array.length, or create a new array each time you want to change the size. If you don't have to use arrays then look at the collections you can use in C#.