I have such struct:
public struct ParsedUser
{
public string Username;
public string pk;
public string RandPhotoId;
}
And I have filled List of ParsedUser:
List<ParsedUser> users;
How to write to file only Usernames?
Something like File.AppendAllLines(tag + ".txt", users.Select(x => new { x.Username} ));
You were close:
File.AppendAllLines(tag + ".txt", string.Join("\r\n", users.Select(u => u.Username)));
First of all you don't need to create a new object, you want just the name, so select it plainly.
Second, ju need to join these strings with "\r\n", a newline plus carriage return, that is what the string.Join does.
You can simply use :
var userNames = users.Select(x => x.Username).ToArray();
File.AppendAllLines(tag + ".txt", userNames);
Method AppendAllLines create new line per every string in IEnumerable<string>.
Related
I wanna do a list without duplicates from a file which have too many lines with identifier, sometimes repeated. When I try using List<string>.Contains, it doesn't work. This is, I think, because I'm adding object instead of strings directly.
public List<string> obterRelacaoDeBlocos()
{
List<string> listaDeBlocos = new List<string>();
foreach(string linhas in arquivos.obterLinhasDoArquivo())
{
string[] linhaQuebrada = linhas.Split('|');
string bloco = linhaQuebrada[1].ToString();
if (listaDeBlocos.Contains((string)bloco) != true)
{
listaDeBlocos.Add( bloco + ":" + listaDeBlocos.Contains(bloco).ToString());
}
}
return listaDeBlocos;
}
You're appending ":" + listaDeBlocos.Contains(bloco).ToString() to the string before you add it to the list. That's not going to match when you encounter the same word again, so Contains will return false and the same word will get added again.
I don't see what point it serves to append ": true" to the end of each string in the list anyway, so just remove that part and it should work.
if (!listaDeBlocos.Contains(bloco))
{
listaDeBlocos.Add(bloco);
}
Since you're only interested in one part of each string, based on how you're splitting, you could rewrite your method using LINQ. This is untested but should work:
public List<string> obterRelacaoDeBlocos()
{
return arquivos.obterLinhasDoArquivo().Select(x => x.Split('|')[1]).Distinct().ToList();
}
I am picking distinct values from a datatable column like below.
var uniqueCC = dtNew.AsEnumerable().Select(s => new { cc = s.Field<string>("ID"), }).Distinct().ToList();
var uniqueCode = dtNew.AsEnumerable().Select(s => new { Code = s.Field<string>("EAI"), }).Distinct().ToList();
Now I need to get the values alone in a comma seperated string and I'm using the below code and it doesn't take the value alone.
string strCC = String.Join(",", uniqueCC);
string strEAI = String.Join(",", uniqueCode);
Please provide some suggestions.
List values
cc=1, cc=2, cc=3
Expected Result
1,2,3
You can just use LINQ Select() method to pass the value alone to String.Join() :
string strCC = String.Join(",", uniqueCC.Select(o => o.cc));
Or just return string values instead of anonymous type in the first place :
var uniqueCC = dtNew.AsEnumerable().Select(s => s.Field<string>("ID")).Distinct();
string strCC = String.Join(",", uniqueCC);
You can use aggregate functions available in c#.
Let say you have a list of string called listOfString, then you can call the aggregate function like this.
string outString = listOfString.Aggregate((a, b) => a + "," + b);
It will do the trick.
As an extension to har07's excellent answer, if this is something you do a lot of the time, to save writing loads of code you could implement this as a static extension method, where you pass the datatype, the column name and your required separator - so it could handle different column datatypes and separators - in a separate file:
namespace Extensions
{
public static class LinqExtensions
{
public static String ReturnSeparatedString<T>(this DataTable datatable, string field, string separator)
{
var unique =
datatable.AsEnumerable()
.Select(s => new {cc = s.Field<string>(field),}).Distinct();
return String.Join(separator, unique.Select(o => o.cc));
}
}
}
Then call it from your code by creating a reference to your new Extensions.LinqExtensions class, and calling it directly on the dataTable like this:
var commaSeparatedIds = dataTable.ReturnSeparatedString<string>("ID",",");
var commaSeparatedEAIs = dataTable.ReturnSeparatedString<string>("EAI",",");
var commaSeparatedInts = dataTable.ReturnSeparatedString<int>("MYINTS",",");
var dotSeparatedStrings = dataTable.ReturnSeparatedString<int>("OtherId", ".");
Okay so I am stumped and have looked around for this and I know I am doing the implementation of something very simple more complex than it needs to be. Basically I have a POCO object that will have a member that contains a string of other members. This is labeled as 'st' and it may have strings that are comma seperated series in one string. Thus I may have two members of strings be 'images, reports' and another 'cms, crm'. I have a list of objects that I want to match for PART OF those strings but not necessarily all as a DISTINCT LIST. So a member of 'cms' would return the value of anything that contained 'cms' thus 'cms, crm' would be returned.
I want to hook this up so a generic List can be queried but I cannot get it to work and was looking at other threads but there methods do not work in my case. I keep thinking it is something simple but I am missing it completely. Please let me know if anyone has better ideas. I was looking here but could not get the logic to apply correctly:
Linq query list contains a list
I keep trying methods of 'Select', 'SelectMany', 'Contains', 'Any', 'All' at different levels of scope of the continuations to no avail. Here is a simple excerpt of where I am at with a simple Console app example:
public class Program
{
public class StringModel
{
public string name { get; set; }
public string str { get; set; }
}
static void Main(string[] args)
{
string s = "";
List<StringModel> sm = new List<StringModel>
{
new StringModel
{
name = "Set1",
str = "images, reports"
},
new StringModel
{
name = "Set2",
str = "cms, crm"
},
new StringModel
{
name = "Set3",
str = "holiday, pto, cms"
}
};
sm.ForEach(x => s += x.name + "\t" + x.str + "\n");
var selected = new List<object> {"cms", "crm"};
s += "\n\nITEMS TO SELECT: \n\n";
selected.ForEach(x => s += x + "\n");
s += "\n\nSELECTED ITEMS: \n\n";
// works on a single item just fine
var result = sm.Where(p => p.str.Contains("cms")).Select(x => new { x.name, x.str}).ToList();
// I am not using select to get POCO on other methods till I can get base logic to work.
// Does not return anything
var result2 = sm.Where(p => selected.Any(x => x == p.str)).ToList();
// Does not return anything
var result3 = sm.Where(p => selected.Any(x => selected.Contains(p.str))).ToList();
result.ForEach(y => s += y + "\n");
s += "\n\n2nd SET SELECTED: \n\n";
result2.ForEach(y => s += y + "\n");
s += "\n\n3rd SET SELECTED: \n\n";
result3.ForEach(y => s += y + "\n");
Console.WriteLine(s);
Console.ReadLine();
}
}
result2 is empty because you're comparing an object (x) with a string (StringModel.str). This will be a reference comparison. Even if you convert x to a string, you'll be comparing each value in selected ("cms", "crm") with your comma-separated string values ("images, reports", "cms, crm", "holiday, pto, cms").
result3 is empty because selected ("cms", "crm") does not contain any of the string values ("images, reports", "cms, crm", "holiday, pto, cms"), although in this case at least the comparisons are value comparisons.
I think you're looking for something like:
var result = sm.Where(p => selected.Any(x => p.str.Contains((string)x)));
I have a class called user that contains a list of groups that are strings ( Group A, Group B, Group C)
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public User()
{
Groups = new List<string>();
}
}
I am then using a json deserializer to create the list of users and groups. However I would like to be able to get a string of the groups with this format for each user:
"Group A", "Group B", "Group C"
I have tried this:
string[] AllGroups;
AllGroups = (string[])usrList[0].Groups.ToArray();
return string.Join(",", AllGroups);
However it is giving me a list in this format (with no quotes):
Group A, Group B, Group C
Any idea what I am doing wrong here?
Any idea what I am doing wrong here?
Well you're not adding the quotes anywhere - so you're not getting them.
You can surround each item with quotes yourself easily enough:
return string.Join(", ", usrList[0].Groups.Select(x => "\"" + x + "\""));
That's assuming you're using .NET 4 or higher - if you're using .NET 3.5 (which doesn't have quite as good string.Join support) you need to create an array, but you don't need to cast it to string[] (as ToArray already returns an array)...
return string.Join(", ", usrList[0].Groups
.Select(x => "\"" + x + "\"")
.ToArray());
I've added a space after the comma delimiter as well, given your question - I suspect your current code is really giving you Group A,Group B,Group C.
Assuming you want to get "" as a result when there are no values, you can do this:
return "\"" + string.Join("\", \"", AllGroups) + "\"";
Note that this is not an empty string - it's a string which contains two quotes.
If you want to return null or the empty string using this code, you'd need to check the size of AllGroups first.
var AllGroups = usrList[0].Groups;
if (AllGroups.Count() == 0) return null;
else return "\"" + string.Join("\", \"", AllGroups) + "\"";
I have a list with multiple variables and would like to add to an array the write to a text file.
class DataFields
{
public string name{get;set;}
public int id{get;set;}
public int age{get;set;}
}
List<DataFields> dfList;
would look something like
Adam 1234 23
Pete 3841 15
Scot 8435 30
DataFields[] result = dfList.ToArray();
File.WriteAllLines(#"C:\File\TextFile.txt", result);
I would like the result to be displayed in the text file similar to the list above but I am having trouble adding the list to the array then display in that order. Any ideas?
File.WriteAllLines wants a collection of strings. You can generate one using LINQ:
List<DataFields> dfList = new List<DataFields>();
// populate dfList here
var formattedData =
dfList
.OrderBy(df => df.Name)
.Select(df => string.Format("{0} {1} {2}", df.Name, df.Id, df.Age));
File.WriteAllLines(#"C:\File\TextFile.txt", formattedData);
You should use PascalCase for your property names (Name, Id, Age).
var result = dfList.Select(df => String.Format("{0}\t{1}\t{2}", df.name, df.id, df.age);
you could do something like this too..
List<DataFields> dfList = new List<DataFields>();
// populate dfList here
StreamWriter sw = new StreamWriter(#"C:\File\TextFile.txt");
foreach (DataFields df in dfList)
{
sw.WriteLine(df.id+"\t"+df.name+"\t"+df.age);
}
sw.Close();
or simply use foreach of List which is more efficient.
dfList.ForEach(df=> sw.WriteLine(df.id + "\t" + df.name + "\t" + df.age));