I have a list of objects call Person I would like to create a tab delimited string from the list
Example:
public class Person
{
public string FirstName { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
}
List<Person> persons = new List<Persons>();
persons.add ( new person {"bob",15,"999-999-0000"} )
persons.add ( new person {"sue",25,"999-999-0000"} )
persons.add ( new person {"larry",75,"999-999-0000"} )
I would like to output that list to a string that would look like this:
"bob\t15\t999-999-0000\r\nsue\t25\999-999-0000\r\nlarry\t75\999-999-0000\r\n"
right now I was just going to loop through the list and do it line by line the old fashion way.. I was wondering if the was a short cut in LINQ.
Aggregate formatted person strings with StringBuilder. Thus you will avoid creating lot of strings in memory:
var result = persons.Aggregate(
new StringBuilder(),
(sb, p) => sb.AppendFormat("{0}\t{1}\t{2}\r\n", p.FirstName, p.Age, p.Phone),
sb => sb.ToString());
You can Use Strig.Join
string str = string.Join(Environment.NewLine, person.Select(r=> r.FirstName +#"\t" +
r.Age + #"\t" +
r.Phone"))
persons.ForEach(q => output+=(q.firstname+"\\"+q.Age.ToString()+"\\"+q.Phone+"\\"));
Related
Does anyone know how to convert a string which contains json that has no parameter names into a C# array. My code receives json from RESTApi That looks like this
[["name","surname","street","phone"],
["alex","smith","sky blue way","07747233279"],
["john","patterson","richmond street","07658995465"]]
Every example I have seen here involved parameter names and their json looked like this
[Name:"alex",Surname:"smith",street:"sky blue way",phone:"07747233279"],
[Name:"john",Surname:"patterson",street:"richmond street",phone:"07658995465"]]
I am trying to use JavaScriptSerializer but i don't know how to properly maintain a Class for such type of JSON
This is not quite what the OP is asking (2d array), but my approach to this problem.
It seems that you have a collection of people, so I'd create a Person class like this:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public string Street { get; set; }
public string Phone { get; set; }
}
And then a parser class that takes the json string as a parameter, and returns a collection of Person:
public class PersonParser
{
public IEnumerable<Person> Parse(string content)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
if (string.IsNullOrWhiteSpace(content))
{
yield break;
}
// skip 1st array, which contains the property names
var values = JsonConvert.DeserializeObject<string[][]>(content).Skip(1);
foreach (string[] properties in values)
{
if (properties.Length != 4)
{
// ignore line? thrown exception?
// ...
continue;
}
var person = new Person
{
Name = properties[0],
Surname = properties[1],
Street = properties[2],
Phone = properties[3]
};
yield return person;
}
}
}
Using the code:
string weirdJson = #"[[""name"",""surname"",""street"",""phone""],
[""alex"",""smith"",""sky blue way"",""07747233279""],
[""john"",""patterson"",""richmond street"",""07658995465""]]";
var parser = new PersonParser();
IEnumerable<Person> people = parser.Parse(weirdJson);
foreach (Person person in people)
{
Console.WriteLine($"{person.Name} {person.Surname}");
}
You could do this, which will give you a list of list of string
var input = "[[\"name\", \"surname\", \"street\", \"phone\"],\r\n\t[\"alex\", \"smith\", \"sky blue way\", \"07747233279\"],\r\n\t[\"john\", \"patterson\", \"richmond street\", \"07658995465\"]]";
var results = JsonConvert.DeserializeObject<List<List<string>>>(input);
foreach (var item in results)
Console.WriteLine(string.Join(", ", item));
Output
name, surname, street, phone
alex, smith, sky blue way, 07747233279
john, patterson, richmond street, 07658995465
Full Demo Here
I'm working on a homework problem for my computer science class. A cities census data is on a text file holding records for its citizens. Each line will have four fields(age, gender, marital status, and district) of different data types separated by a comma. For example, 22, F, M, 1.
How should I approach this? My thoughts are that I should use two 1D arrays, one for age and one for district. I need to be able to later count how many people are in each district, and how many people are in different age groups for the whole city.
How do I read each line and get the info I want into each array?
edit**
This is what I've managed to do so far. I'm trying to separate my data from fields into four different arrays. This is where I'm stuck.
FileStream fStream = new FileStream("test.txt", FileMode.Open, FileAccess.Read);
StreamReader inFile = new StreamReader(fStream);
string inputRecord = "";
string[] fields;
int[] ageData = new int[1000];
string[] genderData = new string[1000];
string[] maritalData = new string[1000];
int[] districtData = new int[1000];
inputRecord = inFile.ReadLine();
while (inputRecord != null)
{
fields = inputRecord.Split(',');
int i = 0;
ageData[i] = int.Parse(fields[0]);
genderData[i] = fields[1];
maritalData[i] = fields[2];
districtData[i] = int.Parse(fields[3]);
i++;
inputRecord = inFile.ReadLine();
}
edit 2**
First question, I've decided to use the below code to find out how many citizens are in each district of the census data.
for (int x = 1; x <= 22; x++)
for (int y = 0; y < districtData.Length; y++)
if (districtData[y] == x)
countDist[x]++;
for (int x = 1; x <= 22; x++)
Console.WriteLine("District " + x + " has " + countDist[x] + " citizens");
In my .Writeline when x reaches two digits it throws off my columns. How could I line up my columns better?
Second question, I am not quite sure how to go about separating the values I have in ageData into age groups using an if statement.
It sounds like each of the four fields have something in common... they represent a person surveyed by the census. That's a good time to use a class along the lines of
public class Person
{
public int Age { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public int District { get; set; }
}
Then, just read in all of the lines from the text file (if it's small, it's fine to use File.ReadAllLines()), and then create an instance of Person for each line in the file.
You can create a
List<Person> people;
to hold the Person instances that you parse from the text file.
Since the lines appear to be separated by commas, have a look at String.Split().
UPDATE
The attempt in your edit is pretty close. You keep creating a new i and initializing it to 0. Instead, initialize it outside your loop:
int i = 0;
while (inputRecord != null)
{
fields = inputRecord.Split(',');
Also you may want to trim excess spaces of of your input. If the fields are separated with ", " rather than just "," you will have excess spaces in your fields.
genderData[i] = fields[1].Trim();
maritalData[i] = fields[2].Trim();
How about this?
List<string[]> o = File.ReadAllLines(#"C:\TestCases\test.txt").Select(x => x.Split(',')).OrderBy(y => y[0]).ToList();
Each person is a string array in the list.
Each property is a index in the array eg: age is first.
The above code reads all lines comma delimits them orders them by age and adds them to the list.
public static class PersonsManager
{
public static PersonStatistics LoadFromFile(string filePath)
{
var statistics = new PersonStatistics();
using (var reader = new StreamReader(filePath))
{
var separators = new[] { ',' };
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
continue; //--malformed line
var lParts = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);
if (lParts.Length != 4)
continue; //--malformed line
var person = new Person
{
Age = int.Parse(lParts[0].Trim()),
Gender = lParts[1].Trim(),
MaritalStatus = lParts[2].Trim(),
District = int.Parse(lParts[3].Trim())
};
statistics.Persons.Add(person);
}
}
return statistics;
}
}
public class PersonStatistics
{
public List<Person> Persons { get; private set; }
public PersonStatistics()
{
Persons = new List<Person>();
}
public IEnumerable<Person> GetAllByGender(string gender)
{
return GetByPredicate(p => string.Equals(p.Gender, gender, StringComparison.InvariantCultureIgnoreCase));
}
//--NOTE: add defined queries as many as you need
public IEnumerable<Person> GetByPredicate(Predicate<Person> predicate)
{
return Persons.Where(p => predicate(p)).ToArray();
}
}
public class Person
{
public int Age { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public int District { get; set; }
}
Usage:
var statistics = PersonsManager.LoadFromFile(#"d:\persons.txt");
var females = statistics.GetAllByGender("F");
foreach (var p in females)
{
Console.WriteLine("{0} {1} {2} {3}", p.Age, p.Gender, p.MaritalStatus, p.District);
}
I hope it helps.
How can I parse the following string of name-value pair in C#:
string studentDetail = "StudentId=J1123,FirstName=Jack,LastName=Welch,StudentId=k3342,FirstName=Steve,LastName=Smith"
The purpose of parsing this array is to insert values in DB using Linq to SQL:
[HttpPost]
public ActionResult SaveStudent(string studentDetail)
{
DataContext db = new DataContext();
Student student = new Student();
{
student.StudentID = //StudentID
student.FirstName = //FirstName
student.LastName = //LastName
};
db.Student.InsertOnSubmit(student);
db.SubmitChanges();
return View();
}
What is the best way of approaching this?
You can split on the comma, then on the equals sign. I put the data into a dictionary for easy access.
string input = "StudentId=J1123,FirstName=Jack,LastName=Welch";
Dictionary<string,string> keyValuePairs = input.Split(',')
.Select(value => value.Split('='))
.ToDictionary(pair => pair[0], pair => pair[1]);
string studentId = keyValuePairs["StudentId"];
Note that this isn't validating the input at all to ensure that there are no commas in values, no keys without values, missing keys, etc.
Because the individual student records are not delimited in the input, I would do something like the following:
public class Student
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
and then:
private List<Student> DoSplit(string input)
{
var theReturn = new List<Student>();
input = input.Replace(",StudentId=", "|,StudentId=");
var students = input.Split('|');
foreach (var student in students)
{
var attribs = student.Split(',');
if (attribs.Count() == 3)
{
var s = new Student();
s.Id = attribs[0].Substring(attribs[0].LastIndexOf('='));
s.FirstName = attribs[1].Substring(attribs[1].LastIndexOf('='));
s.LastName = attribs[2].Substring(attribs[2].LastIndexOf('='));
theReturn.Add(s);
}
}
return theReturn;
}
Again, it's a bit naive because if content contains "=", ",", or "|", there will be failures. You should add some checking in there as well.
Eric Petroelje had a very nice answer at https://stackoverflow.com/a/2049079/59996
Try System.Web.HttpUtility.ParseQueryString, passing in everything
after the question mark. You would need to use the System.Web
assembly, but it shouldn't require a web context.
(I'm not sure why these two questions aren't linked)
I was able to parse a string of the form a=1&b=2&c=3 using the following code
NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(submission);
i have an string data array which contains data like this
5~kiran
2~ram
1~arun
6~rohan
now a method returns an value like string [] data
public string [] names()
{
return data.Toarray()
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
List<Person> persons = new List<Person>();
string [] names = names();
now i need to copy all the data from an string array to an list
and finally bind to grid view
gridview.datasoutrce= persons
how can i do it. is there any built in method to do it
thanks in advance
prince
Something like this:
var persons = (from n in names()
let s = n.split('~')
select new Person { Name=s[1], Age=int.Parse(s[0]) }
).ToList();
var persons = names.Select(n => n.Split('~'))
.Select(a => new Person { Age=int.Parse(a[0]), Name=a[1] })
.ToList();
Assuming that the source data are completely valid (i.e. no negative ages, names do not contain '~', every line has both age and name, and so on), here's a very easy implementation:
List<Person> persons = new List<Person>;
foreach (var s in names()) {
var split = s.Split('~');
int age = int.Parse (split[0]);
string name = split[1];
var p = new Person() { Age = age, Name = name };
persons.Add (p);
}
You can also use a Linq query, which is shorter. See Marcelo's Answer for an example.
I have 3 comma separated strings FirstName, MiddleInitial, LastName
I have a class NameDetails:
public class NameDetails
{
public string FirstName { get; set; }
public string MiddleInitial { get; set; }
public string LastName { get; set; }
}
I have the values for strings as:
FirstName ="John1, John2, John3"
MiddleInitial = "K1, K2, K3"
LastName = "Kenndey1, Kenndey2, Kenndey3"
I need to fill the NameDetails List with the values from the comma separated strings.
Any linq for this? I need this for my asp.net mvc (C#) application.
I don't neccesarily advocate this as a good solution but it does what you asked, which is to 'do it in LINQ'.
It is also probably not the most efficient solution.
string FirstName ="John1, John2, John3";
string MiddleInitial = "K1, K2, K3";
string LastName = "Kenndey1, Kenndey2, Kenndey3";
List<String> fn = new List<String>(FirstName.Split(','));
List<String> mi = new List<String>(MiddleInitial.Split(','));
List<String> ln = new List<String>(LastName.Split(','));
IEnumerable<NameDetails> result = from f in fn
join i in mi on fn.IndexOf(f) equals mi.IndexOf(i)
join l in ln on fn.IndexOf(f) equals ln.IndexOf(l)
select new NameDetails {f, i, l};
I used LINQPad to try this out first (with an anonymous class, not the NameDetails calss).
You can use the Linq to CSV library.
Further to my previous answer you could also try:
// some setup
string firstName ="John1, John2, John3";
string middleInitial = "K1, K2, K3";
string lastName = "Kenndey1, Kenndey2, Kenndey3";
var fn = firstName.Split(',');
var mi = middleInitial.Split(',');
var ln = lastName.Split(',');
// the important bit
var s = fn.Select((f, index) => new NameDetails {f, i = mi[index], l = ln[index]});
It will be fragile to the string arrays having unequal numbers of entries.
Credit due to a previous answer on SO.