convert string data array to list - c#

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.

Related

Convert List to List<Dictionary> efficiently without foreach in c# [duplicate]

This question already has answers here:
How can I convert a class into Dictionary<string,string>?
(8 answers)
Closed 4 years ago.
Assume I have a list of class
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Now i need to convert into List of Dictionary as
Assume it as List<Dictionary<key, value>>PersonDict, below is the structure of each indexes of the same. The key name should be dynamically populated as Property name in the class Person.
key : "Id", Value : Person.Id
key : "Name", Value : Person.Name
key : "Age", Value : Person.Age
Can anyone please help, I have already tried "for each" and "Parallel For each" loop but its taking lot of time, I have 3 millions of record to convert and its taking hours.
Here is a working implementation:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// Create some sample records
var persons = new List<Person>(){
new Person(){Id = 1, Name = "Bob", Age = 30},
new Person(){Id = 2, Name = "Jane", Age = 31},
new Person(){Id = 3, Name = "Mary", Age = 32}
};
// Use Reflection to retrieve public properties
var properties = typeof(Person).GetProperties();
// Create a list to store the dictionaries
var listOfDictionary = new List<Dictionary<string, string>>();
// For each person class
foreach(var person in persons){
// Create a new dictionary
var dict = new Dictionary<string,string>();
// For each property
foreach(var prop in properties){
// Add the name and value of the property to the dictionary
dict.Add(prop.Name, prop.GetValue(person).ToString());
}
// Add new dictionary to our list
listOfDictionary.Add(dict);
}
// Check the contents of our list
foreach(var dict in listOfDictionary){
Console.WriteLine(string.Join(",", dict.Keys));
Console.WriteLine(string.Join(",", dict.Values));
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
You mention that you have millions of records to convert. It may be not the best idea to create millions of Dictionary<> instances, nor to keep them all in memory. However, it is difficult to recommend something without knowing what is your end goal.
This is pretty much the same as the other answers here, but using a slightly more terse syntax. Just a matter of preference.
List<Person> persons = new List<Person> {
new Person { Id = 1, Name = "Sally", Age = 10 },
new Person { Id = 2, Name = "Bob", Age = 9 },
};
List<Dictionary<string, string>> listOfDictionaries =
persons
.Select(p => new Dictionary<string, string>
{
["Id"] = p.Id.ToString(),
["Name"] = p.Name,
["Age"] = p.Age.ToString(),
})
.ToList();

Remove elements in a list considering duplicated subelements

I need to remove elements in a single list considering one or more duplicated subelement
Classes
public class Person
{
public int id { get; set; }
public string name { get; set; }
public List<IdentificationDocument> documents { get; set; }
public Person()
{
documents = new List<IdentificationDocument>();
}
}
public class IdentificationDocument
{
public string number { get; set; }
}
Code:
var person1 = new Person() {id = 1, name = "Bob" };
var person2 = new Person() {id = 2, name = "Ted" };
var person3 = new Person() {id = 3, name = "Will_1" };
var person4 = new Person() {id = 4, name = "Will_2" };
person1.documents.Add(new IdentificationDocument() { number = "123" });
person2.documents.Add(new IdentificationDocument() { number = "456" });
person3.documents.Add(new IdentificationDocument() { number = "789" });
person4.documents.Add(new IdentificationDocument() { number = "789" }); //duplicate
var personList1 = new List<Person>();
personList1.Add(person1);
personList1.Add(person2);
personList1.Add(person3);
personList1.Add(person4);
//more data for performance test
for (int i = 0; i < 20000; i++)
{
var personx = new Person() { id = i, name = Guid.NewGuid().ToString() };
personx.documents.Add(new IdentificationDocument() { number = Guid.NewGuid().ToString() });
personx.documents.Add(new IdentificationDocument() { number = Guid.NewGuid().ToString() });
personList1.Add(personx);
}
var result = //Here comes the linq query
result.ForEach(r => Console.WriteLine(r.id + " " +r.name));
Expected result:
1 Bob
2 Ted
3 Will_1
Example
https://dotnetfiddle.net/LbPLcP
Thank you!
You can use the Enumerable.Distinct<TSource> method from LINQ. You'll need to create a custom comparer to compare using the subelement.
See How do I use a custom comparer with the Linq Distinct method?
Well, yes, you could use a custom comparer. But that's going to be lots more code than your specific example requires. If your specific example is all you need, this this will work fine:
var personDocumentPairs = personList1
.SelectMany(e => e.documents.Select(t => new {person = e, document = t}))
.GroupBy(e => e.document.number).Select(e => e.First());
var result = personDocumentPairs.Select(e => e.person).Distinct();
along the lines of Adam's solution the trick is to iterate persons and group them by associated document numbers.
// persons with already assigned documents
// Will_2
var duplicate = from person in personList1
from document in person.documents
group person by document.number into groupings
let counter = groupings.Count()
where counter > 1
from person in groupings
.OrderBy(p => p.id)
.Skip(1)
select person;
// persons without already assigned documents
// Bob
// Ted
// Will_1
var distinct = from person in personList1
from document in person.documents
group person by document.number into groupings
from person in groupings
.OrderBy(p => p.id)
.Take(1)
select person;
the orderby is a made up rule for the already assigned documents persons, but your mileage may vary

Selecting single attribute of elements from a list object based on another Hashset's element

I have a list object type of some class,
class person
{
public string id { get; set; }
public string regid { get; set; }
public string name { get; set; }
}
List<person> pr = new List<person>();
pr.Add(new person { id = "2",regid="2222", name = "rezoan" });
pr.Add(new person { id = "5",regid="5555", name = "marman" });
pr.Add(new person { id = "3",regid="3333", name = "prithibi" });
and a HashSet of type string,
HashSet<string> inconsistantIDs = new HashSet<string>();
inconsistantIDs.Add("5");
Now i want to get only all the *regid*s from pr list that contains the id's in the inconsistantIDs HashSet and store them into an another HashSet of type string.
i have tried but can only get all the person that has the id's in inconsistantIDs list(This is only an example).
HashSet<person> persons = new HashSet<person>(
pr.Select(p=>p).Where(p=>
inconsistantIDs.Contains(p.id)
));
Could anyone help me out there?
var regIDs = from p in pr join id in inconsistantIDs on p.id equals id
select p.regid;
HashSet<string> matchingRegIDs = new HashSet<string>(regIDs); // contains: "5555"
I am not sure what is your desired output, but I will try anyway:
HashSet<string> persons = new HashSet<string>(
pr.Select(p=>p.regid)
.Where(p=> inconsistantIDs.Any(i=>p.Contains(i))));

Create a tab delimited string from a list of object

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+"\\"));

parse a string with name-value pairs

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);

Categories

Resources