.Split separating every single character - c#

So I'm using a C# code to separate lines of strings and then further separate them using a comma.
I'm using this two to separate:
dataString = hs_get.text.Split('\n');
stringPairs = new string[dataString.Length][];
for (int o = 0; o < dataString.Length - 1; o++)
{
Debug.Log (o);
stringPairs[o] = dataString[o].Split(',');
//Debug.Log (dataString[o][0] + " --- " + dataString[o][2]);
}
This is the PHP code that feeds this string:
php
// Send variables for the MySQL database class.
$database = mysql_connect('X', 'X', 'X') or die('Could not connect: ' . mysql_error());
mysql_select_db('openfire_scores') or die('Could not select database');
$query = "SELECT * FROM `scores` ORDER by `score` DESC LIMIT 5";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());
$num_results = mysql_num_rows($result);
for($i = 0; $i < $num_results; $i++)
{
$row = mysql_fetch_array($result); // Automatically advances one row after fetching
echo $row['id'] . "," . $row['name'] . "," . $row['score'] . "\n";
}
>
And this is the table thats being used:
id | name | score |
1 | Player 1 | 5 |
2 | Player 2 | 5 |
3 | Player 3 | 7 |
But instead of separating the words between the comma's, it separates every single character INCLUDING the comma and puts that into the array.
What am I doing wrong?
Edit
I should mention I built off of this post: http://answers.unity3d.com/questions/16225/how-can-i-read-data-from-a-text-file-putting-a-lar.html
Edit 2
So today I had a breakthrough. This is the code I use now. I am still not sure why the previous code didn't work, but this one does.
dataString = hs_get.text.Split('\n');
stringPairs = new string[dataString.Length][];
for (int o = 0; o < dataString.Length; o++)
{
string[] trial = dataString[o].Split(',');
stringPairs[o] = trial;
}
Thanks for the all the help guys!

Your code appears to work but skips the last row, you should drop the -1 unless you intend to skip the last row.
Here is an example:
string text = "1,Player 1,5\n2,Player 2,5\n3,Player 3,7";
string [] dataString = text.Split('\n');
string [][] stringPairs = new string[dataString.Length][];
for (int o = 0; o < dataString.Length; o++)
{
//Debug.Log(o);
stringPairs[o] = dataString[o].Split(',');
//Debug.Log (dataString[o][0] + " --- " + dataString[o][2]);
}
the array looks as follows:
stringPair[0]
[0]1
[1]Player 1
[2]5
stringPair[1]
[0]2
[1]Player 2
[2]5
stringPair[2]
[0]3
[1]Player 3
[2]7

You don't have to mirror the way the PHP code does it.
You could write something like this:
private string[][] Work(string hs_get_text) {
var lines = hs_get_text.Split('\n');
int linesLength = lines.Length;
var pairs = new List<string[]>(linesLength);
foreach (var line in lines) {
pairs.Add(line.Split(','));
}
return pairs.ToArray();
}
The List class is very powerful. If you are in .Net, you should use it to save some headaches.

Perhaps I am missing something, but this is working fine for me, perhaps a better alternative. I tried recreating the sample from the unity answer.
const string hs_get_text = "apple,ball\ncar,dog\negg,fish\ngoat,hat";
var dataString = hs_get_text.Split('\n');
var list = new List<string[]>(dataString.Length - 1);
foreach (string s in dataString)
{
Debug.WriteLine(s);
list.Add(s.Split(','));
}
And if you needed the list of string to be an array, you can just call .ToArray() on the list.

Related

why method "equals" skips the necessary chars although they are written in unicode?

I splitted csv-file by "," but some numbers were written with using of this symbol so some numbers were splitted on some parts. The beginning and the end of the every splitted number are signed by """ so i tried to paste parts of the number focusing on quotation marks...
string[] inputData = File.ReadAllLines("file.csv");
string[,] allData = new string[inputData.GetLength(0) - 1, 8];
for (int i = 1; i < inputData.GetLength(0); i++)
{
string[] arrayHelpStupied = inputData[i].Split(",");
string[] arrayHelpSmart = new string[8];
int m = 0;
int flagMistake = 0;
string compoundingOfSplittedNumber = "";
Console.WriteLine("\u0022");
for (int j = 0; j < arrayHelpStupied.Length; j++)
{
string prov = arrayHelpStupied[j];
if ((prov[0].Equals("\"")) || (flagMistake == 1))
{
flagMistake = 1;
compoundingOfSplittedNumber += arrayHelpStupied[j];
if (arrayHelpStupied[j][^1].Equals("\u0022"))
{
flagMistake = 0;
arrayHelpSmart[m++] = compoundingOfSplittedNumber;
continue;
}
continue;
}
arrayHelpSmart[m++] = arrayHelpStupied[j];
}
but numbers that start with quotation mark is ignored :(
please could you explain me the reason of such behaviour and how can i cope this difficulty please
If I'm reading the question correctly, you have a CSV file you're splitting on , and some of the "values" you're looking for also have a , in them and you don't want it to split on the , in the value...
Sorry, but it's not going to work. String.Split does not have any overrides, or regex matching. Your best bet is to sanitize your data first by removing the , from the values, or ensuring the , separating your values matches differently than the , in the values.
For example...
12,345 , 23,1566 , 111 , 1
you can split the above on " , " instead of just "," and since the pattern of " , " is consistent, then it will work
Alternately, you could open your csv in Excel and save it as a Tab delimited text file and then split on the tab "/t" character

How to break string by character and line length, without breaking words?

I want to break a long string by character and line length, without breaking words.
Within my string I use "|" as my seperator, and every line must never end with a seperator. I need to break on "|", without breaking words.
I tried the following, which looks at the maximum line length, and makes sure everything fits. Now I have to implement the seperation by "|" character without interupting the check for line length.
int partLength = 35;
string sentence = "Silver badges are awarded for longer term goals. Silver badges are uncommon.";
string[] words = sentence.Split(' ');
var parts = new Dictionary<int, string>();
string part = string.Empty;
int partCounter = 0;
foreach (var word in words)
{
if (part.Length + word.Length < partLength)
{
part += string.IsNullOrEmpty(part) ? word : " " + word;
}
else
{
parts.Add(partCounter, part);
part = word;
partCounter++;
}
}
parts.Add(partCounter, part);
foreach (var item in parts)
{
Console.WriteLine(item.Value);
}
I tried the following for breaking by character "|":
string sentence = "The dog had a bone | a ball | and other toys.";
char charToTrim = '|';
string[] words = sentence.Split();
foreach (string word in words)
Console.WriteLine(word.TrimEnd(charToTrim));
This will print all words on new line, which is not correct.
So in a long text, I need to look at the maximum line length, as well as the seperator "|". The words must match within the line, but a new line cannot end with "|".
So the following is correct:
Item 1 | Item 2 | Item 3 | Item 4
| Item 5 | Etc
But the following is not correct:
Item 1 | Item 2 | Item 3 | Item 4 |
Item 5 | Etc
You can't split the string using the | as you would lose the information about where they existing in the original string. Also you won't be able to do this with foreach as you need to look ahead when calculating the length of the next string. Taking your original code you can do this:
int partLength = 35;
string sentence = "Item 1 | Item 2 | Item 3 | Item 4 | Item 5 | Etc";
string[] words = sentence.Split(' ');
var parts = new Dictionary<int, string>();
string part = string.Empty;
int partCounter = 0;
for(int i = 0; i < words.Count(); i++)
{
var newLength = part.Length + words[i].Length;
if(words[i] == "|" && i + 1 < words.Count())
{
newLength += words[i + 1].Length;
}
if (newLength < partLength)
{
part += string.IsNullOrEmpty(part) ? words[i] : " " + words[i];
}
else
{
parts.Add(partCounter, part);
part = words[i];
partCounter++;
}
}
parts.Add(partCounter, part);
foreach (var item in parts)
{
Console.WriteLine(item.Value);
}
We still split on a space but we use a for loop to iterate through the strings. Before we check if the current word fits we need to check if it is a |. If it is then add the next word as well (if one exists). This should produce the output you are looking for.
Modifying your example (and following your initial approach) I was able to do it like this (the idea is to look one more word ahead in case we meet the separator):
int partLength = 15;
string sentence = "Item1 | Item2 | Item3 | Item4 | Item5 | Item6 | Item7 |";
string[] words = sentence.Split(' ');
var parts = new List<string>();
var partBuilder = new StringBuilder(partLength);
int partCounter = 0;
for (int i = 0; i < words.Length; i++)
{
var word = words[i];
var nextWord = (i < words.Length - 1)
? words[i + 1]
: null;
var lengthToCheck =
word == "|" && nextWord != null
? word.Length + nextWord.Length
: word.Length;
if (partBuilder.Length + lengthToCheck < partLength)
{
if (partBuilder.Length > 0)
partBuilder.Append(" ");
partBuilder.Append(word);
}
else
{
parts.Add(partBuilder.ToString());
partBuilder.Clear();
partBuilder.Append(word);
partCounter++;
}
}
parts.Add(partBuilder.ToString());
foreach (var item in parts)
{
Console.WriteLine(item);
}
The output is:
Item1 | Item2
| Item3 | Item4
| Item5 | Item6
| Item7 |
I also replaced concatenation of strings by StringBuilder which is considered the best practice when it comes to concatenating a lot of strings.
And I still have guts feeling that it's even easier to solve this by moving through the string char by char.

How to read & write first line of text file in C#?

I need to write first line of a text file, which is a name of the company while the other 3 lines is information (described in class).
I have a text file like this:
Turistines keliones;
Poilsine; 7; Italija; 500; Atostogauti;
Pazintine; 5; Cekija; 200; Pamatyti;
Turistine; 4; Kroatija; 350; Ivairiai;
I have written this and I don't know how to write the name.
static void SpausdintiKeliones(string fv, List<Firma1> _firmosKeliones)
{
using (var fr = new StreamWriter(File.Open(fv, FileMode.Append), Encoding.GetEncoding(1257)))
{
fr.WriteLine("| Nr. | Keliones tipas | Keliones trukme (dienomis) | Vietove | Kaina (eurais) | Keliones aprasymas |");
for (int i = 0; i < _firmosKeliones.Count; i++)
{
Firma1 kelione = _firmosKeliones[i];
fr.WriteLine("|{0, 4} {1}", i + 1, kelione);
}
fr.WriteLine("");
}
}
You are adding the blank line inside your method.
Consider removing the line:
fr.WriteLine("");

Different program outputs when different capacity arguments are passed to List constructor, C#

I'm implementing a slightly fancier version of counting sort in C#. The "slightly fancier" part is that I replace some elements in the sorted output with "-" rather than the original value. Here is a sample input/ output pair (the range of possible integer values are between 0 and 99):
IN
20
0 ab
6 cd
0 ef
6 gh
4 ij
0 ab
6 cd
0 ef
6 gh
0 ij
4 that
3 be
0 to
1 be
5 question
1 or
2 not
4 is
2 to
4 the
OUT
- - - - - to be or not to be - that is the question - - - -
And here is my implementation:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
List<List<string>> rsltLists = new List<List<string>>(100);
for(int i=0; i<n; i++)
{
rsltLists.Add(new List<String>()); // PROBLEM IS HERE
}
for(int a0 = 0; a0 < n; a0++)
{
string[] tokens_x = Console.ReadLine().Split(' ');
int x = Convert.ToInt32(tokens_x[0]);
string s = tokens_x[1];
if(a0 < n/2)
{
// Replace string with '-'
rsltLists[x].Add("-");
}
else
{
rsltLists[x].Add(s);
}
}
foreach(List<string> rsltList in rsltLists)
{
foreach(string rslt in rsltList)
{
Console.Write(rslt + " ");
}
}
}
}
I'm submitting my code as the solution to a problem on Hackerrank. The problem is that for the 5th test case, my solution times out (the test case contains an enormous number of lines so I'm not including it here). To speed my solution up, I replaced the //PROBLEM IS HERE line with rsltLists.Add(new List<String>(100)). This causes the 5th test case to fail rather than time out (test cases 1-4 still passed). When I replaced the problem line with rsltLists.Add(new List<String>(10000)) the 5th test case and several other test cases failed (though not all of the test cases failed). Why would changing the amount of space I reserve for each List<String> cause this inconsistent behavior? I would expected the fifth test case to fail (maybe), but I wouldn't have expected test cases that were passing previously to start failing.
Why are you creating n rsltLists? That is not the requirement. There are 100 possible values and array is better for that. You should NOT be using n here. x is 100.
for(int i=0; i<n; i++) // no, problem is here
{
rsltLists.Add(new List<String>()); // PROBLEM IS HERE
}
This should be pretty fast
public static string HackerSort()
{
List<string> input = new List<string>() {"20"
, "0 ab"
, "6 cd"
, "0 ef"
, "6 gh"
, "4 ij"
, "0 ab"
, "6 cd"
, "0 ef"
, "6 gh"
, "0 ij"
, "4 that"
, "3 be"
, "0 to"
, "1 be"
, "5 question"
, "1 or"
, "2 not"
, "4 is"
, "2 to"
, "4 the" };
List<string>[] wl = new List<string>[100];
int n = int.Parse(input[0]);
int half = n/2;
char split = ' ';
for (int i = 0; i < n; i++)
{
string s = input[i + 1];
string[] ss = s.Split(split);
//Debug.WriteLine(ss[0]);
int row = int.Parse(ss[0]);
if(wl[row] == null)
{
wl[row] = new List<string>((n / 100) + 1);
}
wl[row].Add(i < half ? "-" : ss[1]);
}
StringBuilder sb = new StringBuilder();
foreach(List<string> ls in wl.Where(x => x != null))
{
sb.Append(string.Join(" ", ls) + ' ');
}
Debug.WriteLine(sb.ToString().TrimEnd());
return sb.ToString().TrimEnd();
}
Couple thoughts on this:
You're creating a list for each option... but many aren't used. How about only instantiating the lists that you'll actually use?
Compounded with the one above, you're creating 100 lists, each with a capacity of 100... that's a lot of memory to set aside that you won't be using
One solution:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
class Solution
{
static void Main(String[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
int threshold = n / 2;
List<string>[] stringMap = new List<string>[100];
for(int a0 = 0; a0 < n; a0++){
string[] tokens_x = Console.ReadLine().Split(' ');
int x = Convert.ToInt32(tokens_x[0]);
if(stringMap[x] == null)
{
stringMap[x] = new List<string>();
}
stringMap[x].Add((a0 >= threshold ? tokens_x[1] : "-"));
}
List<string> output = new List<string>();
for(int i = 0; i < stringMap.Length; i++)
{
if(stringMap[i] == null)
{
continue;
}
output.AddRange(stringMap[i]);
}
Console.WriteLine(string.Join(" ", output));
}
}
The "inner" List will always have exactly two elements, one of which you want to treat as a number rather than a string. Better to use a small class or even a tuple here, rather than nested lists.
I'm at work with only VS2015 with no tuple support, so this code is unchecked and likely has a mistake or two:
static void Main(String[] args)
{
int n = int.Parse(Console.ReadLine());
var data = new List<(int, string)>(n);
for(int a0 = 0; a0 < n; a0++)
{
var tokens = Console.ReadLine().Split(' ');
int x = int.Parse(tokens[0]);
if(a0 < n/2) tokens[1] = "-";
data.Add( (val: x, str: tokens[1]) )
}
foreach(var item in data.OrderBy(i => i.val))
{
Console.Write(item.str + " ");
}
}
One way to solve the memory-hogging / long processing times would be to store the input in a SortedDictionary<int, List<string>> instead. The Key would be the integer portion of the input, and the Value would be a List<string> containing the other part of the input (one item per input that matches the key).
Then, when we have the dictionary populated, we can just output each List<string> of data in order (the SortedDictionary will already be sorted by Key).
In this way, we're only creating as many lists as we actually need, and each list is only as long as it needs to be (both of which I believe were causes for the errors in your original code, but I don't know where to find the actual test case code to verify).
private static void Main()
{
var length = Convert.ToInt32(Console.ReadLine());
var halfway = length / 2;
var items = new SortedDictionary<int, List<string>>();
for (int inputLine = 0; inputLine < length; inputLine++)
{
var input = Console.ReadLine().Split();
var sortIndex = Convert.ToInt32(input[0]);
var value = inputLine < halfway ? "-" : input[1];
if (items.ContainsKey(sortIndex)
{
items[sortIndex].Add(value);
}
else
{
items.Add(sortIndex, new List<string> {value});
}
}
Console.WriteLine(string.Join(" ", items.SelectMany(i => i.Value)));
// Not submitted to website, but for local testing:
Console.Write("\n\nPress any key to exit...");
Console.ReadKey();
}
Output

How to remove text from a specific line in file without creating unwanted space using c#?

I'm trying to remove text from a specific line in the file that i have created "Test.txt".
Here is the text written in Test.txt:
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
Now what i want to happen is when i'm going to remove 2 - 4 in the 2nd iteration, the output should be like this:
1
2
3
4
5
1
5
1
2
3
4
5
What i want is to remove only spaces that the corresponding text was removed from and preferably without involving other spaces.
But when i tried the code it gave me this output:
1
2
3
4
5
1
5
1
2
3
4
5
As you can see the above output, that is the unwanted space that i'm talking about. Below is the code that I have tried:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestCode
{
class Program2
{
static void Main()
{
lineChanger("", #"C:\Users\User1\Documents\Visual Studio 2015\WebSites\MusicStore\Pages\Test.txt", 8);
lineChanger("", #"C:\Users\User1\Documents\Visual Studio 2015\WebSites\MusicStore\Pages\Test.txt", 9);
lineChanger("", #"C:\Users\User1\Documents\Visual Studio 2015\WebSites\MusicStore\Pages\Test.txt", 10);
}
static void lineChanger(string newText, string fileName, int line_to_edit)
{
string[] arrLine = File.ReadAllLines(fileName);
arrLine[line_to_edit - 1] = newText;
File.WriteAllLines(fileName, arrLine);
}
}
}
Also please feel free to suggest any proper techniques and kindly include actual examples.
Please see is this ok?
int removeAt = 7; //or any thing you want
int linesToRemove = 3; //or any thing you want
string s = System.IO.File.ReadAllText("Test.txt");
List<string> arr = s.Split("\n".ToCharArray()).ToList();
for (int i = 0; i < linesToRemove; i++)
arr.RemoveAt(removeAt);
string result = "";
foreach (string str in arr)
{
result += str;
}
System.IO.File.WriteAllText("Test.txt", result);
I'm happy that you say it works for you, and here i add another solution, maybe in some cases you need to use this:
int removeAt = 7; //or any thing you want
int linesToRemove = 3; //or any thing you want
string s = System.IO.File.ReadAllText("Test.txt");
List<string> arr = s.Split(new char[] { '\n' }).ToList();
List<int> realBareRows = new List<int>();
for (int i = 0; i < arr.Count; i++)
{
if (string.IsNullOrEmpty(arr[i].Replace("\r", "")))
realBareRows.Add(i);
}
List<string> newArr = s.Split(System.Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
foreach (int j in realBareRows)
newArr.Insert(j, "\n");
for (int i = 0; i < linesToRemove; i++)
newArr.RemoveAt(removeAt);
string result = "";
foreach (string str in newArr)
{
result += str + System.Environment.NewLine;
}
System.IO.File.WriteAllText("Test.txt", result);
I suggest you remove the lines via File.ReadLines. You can do it like this:
foreach (var line in File.ReadLines(fileName))
{
//Add it to your arrLine and don't insert a line based on your condition.
}
I'm not quite sure what's your condition here. I think it's based on the line_to_edit
Hope this helps!
You can omit all the lines with 0 lenght
File.WriteAllLines(fileName, arrLine.Where(x => x.Length>0));

Categories