How to split and save lines from a CSV file in C# - c#

I do have the following CSV file:
34416;15,14;22,67;71,51;73,59;73,1;67,19;64,07;64,29;67,94; ...
...
Now, I would like to save the first number 34416 and replace every semicolon with it, but do not replace the first semicolon.
Now, there is the next line. Same procedure, just another number at the beginning.
public List<string> ConvertFile()
{
string allLines = string.Empty;
allLines = GetLinesFromFile();
for (int i = 0; i < GetLinesFromFile().Length; i++)
{
string[] split = allLines.Split(new Char[] { ';' });
string number = split[i];
allLines.Replace(";", ";34416|");
}
List<string> re = new List<string>();
re.Add(allLines);
return re;
}
I am very new to C# coding - could you please help me?
Thanks in advance.

You need to rethink your logic. First of all GetLinesFromFile() seems to return a string; I'd have that return a List<string> instead (with each line from the file being one string). And then you can do this:
public List<string> ConvertFile()
{
var result = new List<string>();
foreach(var line in GetLinesFromFile())
{
var lineParts = line.Split(';');
var fixedLine = line.Replace(";", ";" + lineParts[0] + "|");
result.Add(fixedLine);
}
return result;
}

try this
public List<string> ConvertFile( )
{
string allLines = GetLinesFromFile();
List<string> re = new List<string>();
for (int i = 0; i < allLines.Length; i++)
{
string[] split = allLines.Split(new Char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
allLines.Replace(";", ";" + split[0] + "|");
re.Add(allLines);
}
return re;
}

Related

Where to add an if statement inside for foreach loop?

I have a CSV file like this:
1,01/01/2001,hello
2,19/09/2013,world
3,12/05/2016,world
4,13/05/2016,hello
5,12/12/2012,world
6,05/02/2006,world
7,06/03/2011,hello
I have this set of code from a question I asked yesterday:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
}
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
The above code works just fine but now I have another problem. I want to add an if statement within the code to only display the chosen value's date and all I could think of is doing either something like this:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
if (data[2] == "hello")
{
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
}
}
Or placing the if statement within the foreach loop, which results in the same output:
01/01/2001
01/01/2001
19/09/2013
12/05/2016
13/05/2016
01/01/2001
05/02/2006
06/03/2011
12/12/2012
19/09/2013
12/05/2016
13/05/2016
It seems to me that you could make your code much simpler with LINQ.
Try this:
var lines = File.ReadAllLines(#"C:\input.txt");
var query =
from line in lines
let data = line.Split(',')
where data[2] == "hello"
orderby DateTime.ParseExact(data[1], "dd/MM/yyyy", null)
select data[1];
var dates = query.ToList();
Label1.Text = String.Join("", dates.Select(x => x + "<br />"));
This handles the if statement you wanted with the where data[2] == "hello" in the query.
One of the things you may want to consider doing instead is to use an intermediate class to represent a csv line, e.g.
private class CSVEntry
{
public int EntryNo { get; set; }
public DateTime Date { get; set; }
public string Text { get; set; }
}
And then change your data loading to:
List<CSVEntry> csvlist = new List<CSVEntry>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
csvlist.Add(new CSVEntry() { EntryNo = Int32.Parse(data[0]), Date = DateTime.ParseExact(data[1], "dd/MM/yyyy", null), Text = data[2] });
}
Then chose what to display by doing something like:
var results = csvlist.Where(x => x.Text == "hello").OrderBy(x => x.Date);
Label1.Text = String.Join("<br />", results.Select(x => x.Date.ToString("dd/MM/yyyy"));
The benefit to doing it this way is that you can re use what you have loaded in previously, and any changes to display new values can be done in a LINQ projection.
Edit:
I suggest you move the 'loading' into a separate function, e.g.
public List<CSVEntry> LoadData(string filename, ... other params) {...
and then the part where you want to find specific entries
public IEnumerable<CSVEntry> FindByName(List<CSVEntry> loadedData, ICollection<string> targetNames)
{
return loadedData.Where(x => targetNames.Contains(x.Text));
}
Moving on, you can call it by passing an array/list to the function
var results = FindByName(csvList, new string[] { "hello", "world"});

how to split comma with double quotes in c#?

string strExample =
"\"10553210\",\"na\",\"398,633,000\",\"20130709\",\"20130502\",\"20120724\",";
how to split above string with ","
I need an answer like
string[] arrExample = YourFunc(strExample);
arrExample[0] == "10553210";
arrExample[1] == "na";
arrExample[2] == "398,633,000";
...
with split option.
thanks in advance
Here is an easy way,
using Microsoft.VisualBasic.FileIO;
IList<string> arrExample;
using(var csvParser = new TextFieldParser(new StringReader(strExample))
{
fields = csvParser.ReadFields();
}
You may split not by comma "," but by whole string "\",\"".
Do not forget to Trim leading and trailing quotations ":
String strExample =
"\"10553210\",\"na\",\"398,633,000\",\"20130709\",\"20130502\",\"20120724\"";
string[] arrExample = St.Trim('"').Split(new String[] {"\",\""}, StringSplitOptions.None);
You can split on "," , The first and last entry you have to clean the " in the last and first entry:
string[] arr = strExample .Split(new string[] { "\",\"" },
StringSplitOptions.None);
//remove the extra quotes from the last and the first entry
arr[0] = arr[0].SubString(1,arr[0].Length - 1);
int last = arr.Length - 1;
arr[last] = arr[last].SubString(0,arr[last].Length - 1);
string[] arrExample = strExample.Split(",");
would do it, but your code won't compile. I assume you meant:
string strExample = "10553210,na,398,633,000,20130709,20130502,20120724";
If this isn't what you meant, please correct the question.
Assuming you meant this:
string strExample = "\"10553210\",\"na\",\"398,633,000\",\"20130709\",\"20130502\",\"20120724\"";
Split then Select the substring:
string[] parts = strExample.Split(',').Select(x => x.Substring(1, x.Length - 2)).ToArray();
Result:
strExample.Split(',');
You need to escape the double quotes if they're meant to be contained in your example string.
Using the example from Jodrell
private string[] SplitFields(string csvValue)
{
//if there aren't quotes, use the faster function
if (!csvValue.Contains('\"') && !csvValue.Contains('\''))
{
return csvValue.Trim(',').Split(',');
}
else
{
//there are quotes, use this built in text parser
using(var csvParser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(csvValue.Trim(','))))
{
csvParser.Delimiters = new string[] { "," };
csvParser.HasFieldsEnclosedInQuotes = true;
return csvParser.ReadFields();
}
}
}
This worked for me
public static IEnumerable<string> SplitCSV(string strInput)
{
string[] str = strInput.Split(',');
if (str == null)
yield return null;
StringBuilder quoteS = null;
foreach (string s in str)
{
if (s.StartsWith("\""))
{
if (s.EndsWith("\""))
{
yield return s;
}
quoteS = new StringBuilder(s);
continue;
}
if (quoteS != null)
{
quoteS.Append($",{s}");
if (s.EndsWith("\""))
{
string s1 = quoteS.ToString();
quoteS = null;
yield return s1;
}
else
continue;
}
yield return s;
}
}
static void Main(string[] args)
{
string s = "111,222,\"33,44,55\",666,\"77,88\",\"99\"";
Console.WriteLine(s);
var sp = SplitCSV(s);
foreach (string s1 in sp)
{
Console.WriteLine(s1);
}
Console.ReadKey();
}
you can do that by doing this ..
string stringname= "10553210,na,398,633,000,20130709,20130502,20120724";
List<String> asd = stringname.Split(',');
or if you wanr array then
array[] asd = stringname.Split(',').ToArray;

Split a separated string into hierarchy using c# and linq

I have string separated by dot ('.') characters that represents a hierarchy:
string source = "Class1.StructA.StructB.StructC.FieldA";
How can I use C# and linq to split the string into separate strings to show their hierarchy? Such as:
string[] result = new string[]
{
"Class1",
"Class1.StructA",
"Class1.StructA.StructB",
"Class1.StructA.StructB.FieldA"
};
Split the string by the delimiters taking 1...N of the different levels and rejoin the string.
const char DELIMITER = '.';
var source = "Class1.StructA.StructB.StructC.FieldA";
var hierarchy = source.Split(DELIMITER);
var result = Enumerable.Range(1, hierarchy.Length)
.Select(i => String.Join(".", hierarchy.Take(i)))
.ToArray();
Here's a more efficient way to do this without LINQ:
const char DELIMITER = '.';
var source = "Class1.StructA.StructB.StructC.FieldA";
var result = new List<string>();
for (int i = 0; i < source.Length; i++)
{
if (source[i] == DELIMITER)
{
result.Add(source.Substring(0, i));
}
}
result.Add(source); // assuming there is no trailing delimiter
Here is solution that uses aggregation:
const string separator = ".";
const string source = "Class1.StructA.StructB.StructC.FieldA";
// Get the components.
string[] components = source.Split(new [] { separator }, StringSplitOptions.None);
List<string> results = new List<string>();
// Aggregate with saving temporary results.
string lastResult = components.Aggregate((total, next) =>
{
results.Add(total);
return string.Join(separator, total, next);
});
results.Add(lastResult);
Here's a solution completely without LINQ:
public static string[] GetHierarchy(this string path)
{
var res = path.Split('.');
string last = null;
for (int i = 0; i < res.Length; ++i)
{
last = string.Format("{0}{1}{2}", last, last != null ? "." : null, res[i]);
res[i] = last;
}
return res;
}
Shlemiel the painter approach is better than the "super Shlemiel" string.Join in this case.
const char DELIMITER = '.';
string soFar = "";
List<string> result = source.Split(DELIMITER).Select(s =>
{
if (soFar != "") { soFar += DELIMITER; };
soFar += s;
return soFar;
}).ToList();

C# easy way to convert a split string into columns

This is a rough one to explain. What I have is a string,
string startString = "Operations\t325\t65\t0\t10\t400"
string[] splitStart = startString.Split('\t');
I need to turn this into
Operations|325
Operations|65
Operations|0
Operations|10
Operations|400
The problem is i need this so be dynamic to if it has 10 splits I need it to do the same process 10 times, if it has 4, then it needs to do 4.
Any help would be awesome.
Sorry for any confusion, Operations is just this string, so it's not static. It really need to be [0] of the string split.
Something like:
string startString = "Operations\t325\t65\t0\t10\t400"
string[] splitStart = startString.Split('\t');
List<string> result = new List<string>();
if(splitStart.Length > 1)
for(int i = 1; i < splitStart.Length; i++)
{
result.Add(splitStart[0] + "|" + splitStart[i]);
}
If it is the strings you want, a little Linq should be fine:
string startString = "Operations\t325\t65\t0\t10\t400";
var operations = startString.Split('\t').Select(str => "Operations|" + str);
How about this?
var reFormatted = new List<string>();
foreach (var roughOne in toExplain)
{
// example of roughOne "Operations\t325\t65\t0\t10\t400"
var segments = roughOne.Split("\t");
var firstSegment = segments.First();
var sb = new StringBuilder();
foreach (var otherSegment in segments.Skip(1))
{
sb.Append(firstSegment);
sb.Append("|")
sb.Append(otherSegment);
sb.Append("\r\n");
}
reFormatted.Add(sb.ToString());
}

Splitting a string array

I have a string array string[] arr, which contains values like N36102W114383, N36102W114382 etc...
I want to split the each and every string such that the value comes like this N36082 and W115080.
What is the best way to do this?
This should work for you.
Regex regexObj = new Regex(#"\w\d+"); # matches a character followed by a sequence of digits
Match matchResults = regexObj.Match(subjectString);
while (matchResults.Success) {
matchResults = matchResults.NextMatch(); #two mathches N36102 and W114383
}
If you have the fixed format every time you can just do this:
string[] split_data = data_string.Insert(data_string.IndexOf("W"), ",")
.Split(",", StringSplitOptions.None);
Here you insert a recognizable delimiter into your string and then split it by this delimiter.
Forgive me if this doesn't quite compile, but I'd just break down and write the string processing function by hand:
public static IEnumerable<string> Split(string str)
{
char [] chars = str.ToCharArray();
int last = 0;
for(int i = 1; i < chars.Length; i++) {
if(char.IsLetter(chars[i])) {
yield return new string(chars, last, i - last);
last = i;
}
}
yield return new string(chars, last, chars.Length - last);
}
If you use C#, please try:
String[] code = new Regex("(?:([A-Z][0-9]+))").Split(text).Where(e => e.Length > 0 && e != ",").ToArray();
in case you're only looking for the format NxxxxxWxxxxx, this will do just fine :
Regex r = new Regex(#"(N[0-9]+)(W[0-9]+)");
Match mc = r.Match(arr[i]);
string N = mc.Groups[1];
string W = mc.Groups[2];
Using the 'Split' and 'IsLetter' string functions, this is relatively easy in c#.
Don't forget to write unit tests - the following may have some corner case errors!
// input has form "N36102W114383, N36102W114382"
// output: "N36102", "W114383", "N36102", "W114382", ...
string[] ParseSequenceString(string input)
{
string[] inputStrings = string.Split(',');
List<string> outputStrings = new List<string>();
foreach (string value in inputstrings) {
List<string> valuesInString = ParseValuesInString(value);
outputStrings.Add(valuesInString);
}
return outputStrings.ToArray();
}
// input has form "N36102W114383"
// output: "N36102", "W114383"
List<string> ParseValuesInString(string inputString)
{
List<string> outputValues = new List<string>();
string currentValue = string.Empty;
foreach (char c in inputString)
{
if (char.IsLetter(c))
{
if (currentValue .Length == 0)
{
currentValue += c;
} else
{
outputValues.Add(currentValue);
currentValue = string.Empty;
}
}
currentValue += c;
}
outputValues.Add(currentValue);
return outputValues;
}

Categories