c# linq add single quote before & after field values on datatable - c#

i have data table. now, i am converting/export this data table to csv.
for that my code is:
var valueLines = dt.AsEnumerable()
.Select(row => string.Join(",", row.ItemArray));
Here, suppose my fields are **Name Number Rollname RollNumber**.
after this query fire. it convert like: **Name,Number,Rollname,RollNumber**
it's work. i am getting csv file perfect. but issue this.
suppose some filed value like: Roll,Number ...at that time. i am getting 2 fields/cell on csv....i am thinking to add ' before & after field values.
or any another way to skip issue?

CSV accepts items enclosed in double-quotes. You can put double-quotes around each item by modifying your code as follows:
var valueLines = dt.AsEnumerable()
.Select(row => string.Join(
","
, row.ItemArray.Select(s => s.ToString().IndexOf(',') < 0 ? s : string.Format("\"{0}\"", s))));
The above replaces row.ItemArray with a Select that checks each item for ',', and puts double-quotes around strings that have commas.

Yes, one way would be wrap the fields in quotes on use a different delimiter that is rare like ^.
var valueLines = dt.AsEnumerable()
.Select(row => string.Join(",", row.ItemArray
.Select(f => string.Format("\"{0}\"", f))));
or
var valueLines = dt.AsEnumerable()
.Select(row => string.Join("^", row.ItemArray));
In general you should use a CSV-reader instead of reading the strings and splitting them manually. They support quoting characters and many more features. I can recommend this:
http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader

This is easy, remember you can mix old school concatenation with linq:
var valueLine = (from row in dt.AsEnumerable()
select "'" + row.Field("field name") + "'").ToList();

Related

How to modify string list for duplicate values?

I am working on project which is asp.net mvc core. I want to replace string list of duplicate values to one with comma separated,
List<string> stringList = surveylist.Split('&').ToList();
I have string list
This generate following output:
7=55
6=33
5=MCC
4=GHI
3=ABC
1003=DEF
1003=ABC
1=JKL
And I want to change output like this
7=55
6=33
5=MCC
4=GHI
3=ABC
1003=DEF,ABC
1=JKL
Duplicate items values should be comma separated.
There are probably 20 ways to do this. One simple one would be:
List<string> newStringList = stringList
.Select(a => new { KeyValue = a.Split("=") })
.GroupBy(a => a.KeyValue[0])
.Select(a => $"{a.Select(x => x.KeyValue[0]).First()}={string.Join(",", a.Select(x => x.KeyValue[1]))}")
.ToList();
Take a look at your output. Notice that an equal sign separates each string into a key-value pair. Think about how you want to approach this problem. Is a list of strings really the structure you want to build on? You could take a different approach and use a list of KeyValuePairs or a Dictionary instead.
If you really need to do it with a List, then look at the methods LINQ's Enumerable has to offer. Namely Select and GroupBy.
You can use Select to split once more on the equal sign: .Select(s => s.Split('=')).
You can use GroupBy to group values by a key: .GroupBy(pair => pair[0]).
To join it back to a string, you can use a Select again.
An end result could look something like this:
List<string> stringList = values.Split('&')
.Select(s => {
string[] pair = s.Split('=');
return new { Key = pair[0], Value = pair[1] };
})
.GroupBy(pair => pair.Key)
.Select(g => string.Concat(
g.Key,
'=',
string.Join(
", ",
g.Select(pair => pair.Value)
)
))
.ToList();
The group contains pairs so you need to select the value of each pair and join them into a string.

Sorting an array by another array's values using OrderByDescending() does not sort the array

I'm trying to implement a simple Huffman coding algorithm. I take my input string (ddddbbcccaeeeee) and use it to create 2 arrays, those being a char array called usedCharacters and an int array called characterCounts. However these arrays need to be sorted by the number of times the character appears in the input string so the Huffman tree can be constructed. I tried using LINQ's OrderByDescending() method like I had seen online:
usedCharacters = usedCharacters.OrderByDescending(i => characterCounts).ToArray();
characterCounts = characterCounts.OrderByDescending(i => i).ToArray();
The program runs but when I check the results the characters are very obviously still in order as they appear in the input string, meaning no sorting is actually done. On the other hand, characterCounts does succesfully sort. I also tried the more commonly seen online solution of usedCharacters.OrderByDescending(i => characterCounts.IndexOf(i)).ToArray() but that just causes an index out of bounds exception for reasons I don't fully understand. If anybody could give me some insight into what I'm missing that would be greatly appreciated. Thank you!
The simplest way to achieve what you're trying to do is to use a GroupBy expression.
var s = "ddddbbcccaeeeee";
var list = s.GroupBy(x => x)
.Select(x => new { Char = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count);
foreach(var item in list)
{
Console.WriteLine(item.Char + " " + item.Count);
}
The code treats s as a character array and counts instances of all characters. The OrderByDescending then sorts by Count.
The output of code below should look something like this:
e 5
d 4
c 3
b 2
a 1
Your LINQ statement is trying to sort each element in usedCharacters by an by a constant int[]. It doesn't do anything like matching up the elements of both arrays. It's exactly as if you are doing this:
usedCharacters = usedCharacters.OrderByDescending(i => 42).ToArray();
It just leaves the array in the same order.
If you have two separate list and you want to order the first based on the second then you need to use Zip like this:
usedCharacters =
usedCharacters
.Zip(characterCounts)
.OrderByDescending(x => x.Second)
.Select(x => x.First)
.ToArray();
If you have the initial string of characters then this is the simplest way to get your result:
string characters = "ddddbbcccaeeeee";
char[] usedCharacters =
characters
.GroupBy(x => x)
.OrderByDescending(x => x.Count())
.Select(x => x.Key)
.ToArray();

DataTable Rows to single Row Using LINQ

I have a single column with multiple rows in a DataTable, I want them In a single row, and dont want to loop through each row of data table,
Here is Sample Data Table
Results
-------
Clinet1
Clinet2
Clinet3
Clinet4
I want to get a string like
Clinet1,Clinet2,Clinet3,Clinet4 but using LINQ without for loop.
I tried code below but its not working for me
string Details = myDataTable.Rows
.Cast<DataRow>()
.Where(x => x["Results"].ToString();
Using LINQ:
string Details = myDataTable.Rows.Cast<DataRow>()
.Where(x => x["Results"] == UserName)
.Select(i => i.ToString()).Aggregate((i, j) => i + "," + j)
Use String.join for this.
string Details = String.join(",", myDataTable.Rows
.Cast<DataRow>()
.Where(x => x["Results"] == UserName).ToArray());
You can use AsEnumerable to return an IEnumerable<T> object, where the generic parameter T is DataRow and String.Join to join rows into a string like this;
string rows = string
.Join(",", myDataTable.AsEnumerable()
.Select(x => x["Results"]));

read text file and writing to a list

Is their a way to split a text file in multiple places all at once and save to a list?
I was able to do the split in one place and write to a list like this:
var incomplete = File
.ReadAllLines(path)
.Select(a => a.Split(new[] { '|' }, StringSplitOptions.None)[5].Trim())
.ToList();
I would like to split in four locations and then write to a list.
var mnbrs = File
.ReadAllLines(path)
.Select(a => a.Split('|')[2].Trim())
.Select(b => b.Split('|')[5].Trim())
.Select(c => c.Split('|')[6].Trim())
.Select(d => d.Split('|')[11].Trim())
.ToList();
this gives me error index was outside of bounds of array.
Any help is appreciated.
Am also open to split and read filing in a different manner as well.
I just would like to avoid reading file split once then to list then reading agian and splitting again and doing it four times.
You want to do it in two steps. First split, then select the individual columns:
File
.ReadAllLines(path)
.Select(a => a.Split(new[] { '|' }, StringSplitOptions.None))
.Select(a => new {
Column1 = a[2].Trim(),
Column2 = a[5].Trim(),
Column3 = a[6].Trim(),
Column4 = a[11].Trim()
})
.ToList();
Demo: http://ideone.com/aNyNT5

Split a LINQ string list

I believe this could be another easy one for you LINQ masters out there.
I have a table with a field that consists of strings delimited by "#". After I select the field using LINQ, how can I split each of the strings into a different list?
My string list looks like:
#A#B#C#D#G#F
I used a simple LINQ query to access this:
from x in Special_texts
where x.Name.Equals("ExceptionList")
select x.Content
In the end, my list should contain:
A
B
C
D
G
F
Thanks in advance.
Assuming you want a single list as output:
var list = Special_texts.Where(x=> x.Name.Equals("ExceptionList"))
.Select(x=> x.Content)
.AsEnumerable()
.Select(x=> x.Split(new [] {'#'}, StringSplitOptions.RemoveEmptyEntries))
.SelectMany(x=> x)
.ToList();
Alternatively if you want a list of lists (one for each item in Special_texts):
var list = Special_texts.Where(x=> x.Name.Equals("ExceptionList"))
.Select(x=> x.Content)
.AsEnumerable()
.Select(x=> x.Split(new [] {'#'}, StringSplitOptions.RemoveEmptyEntries).ToList())
.ToList();
from x in Special_texts
where x.Name.Equals("ExceptionList")
select x.Content.Split('#').ToList();

Categories