parse a string with name-value pairs - c#

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

Related

Get all keys from combination of JArray and JObject

I'm new to JSON and looked at all the possible answers, but still not able to get it. Basically I'm getting the list of all users and storing it as string. Below is the result Json output string.
[{"Links":[],"RequestedObject":{"Id":181,"DisplayName":"User, Migration","FirstName":"Migration","MiddleName":null,"LastName":"User","LastLoginDate":"2008-01-10T11:04:00","UserName":"1564134","AccountStatus":2,"DomainId":null,"UpdateInformation":{"CreateDate":"2008-01-10T17:04:24.72","UpdateDate":"2011-10-07T16:35:51.74","CreateLogin":2,"UpdateLogin":2}},"IsSuccessful":true,"ValidationMessages":[]},{"Links":[],"RequestedObject":{"Id":16167,"DisplayName":"Xyz, Abc","FirstName":"Abc","MiddleName":null,"LastName":"Xyz","LastLoginDate":"2022-03-04T15:54:29.43","UserName":"1514834","AccountStatus":1,"DomainId":null,"UpdateInformation":{"CreateDate":"2022-03-04T15:53:14.817","UpdateDate":"2022-03-04T15:54:29.293","CreateLogin":14760,"UpdateLogin":11743}},"IsSuccessful":true,"ValidationMessages":[]}]
As you can see first part is JArray and then Jobject. My requirement is to get all "RequestedObject" that have "CreateDate" greater than or equal to CurrentDate. Is there a simple way to achieve this using linq instead of foreach loop. Here is code that I was able to put in from all other answers.
try
{
string text = System.IO.File.ReadAllText(#"H:\Test.txt");
DateTime previousRunTime = new DateTime(2022, 01, 31);
JArray jsonArray = JArray.Parse(text);
var jsonObjects = jsonArray.OfType<JObject>().ToList();
//var users1 = from item in jsonObjects.Children()["RequestedObject"].Value<string>()
// select item;
var abc = jsonObjects.Properties().Where(p => p.Name == "RequestedObject").Select(p => p.Value);
foreach(var q in abc)
{
Console.WriteLine(q.Value<string>("Id").ToString());
}
}
catch (Exception p)
{
Console.WriteLine(p.Message);
}
Looking for solution something like below
var users =
from item in jsonObjects["RequestedObject"]
where item["UpdateInformation"]["CreateDate"].Value<DateTime>() >= previousRunTime
select new UserDetails
{
UserName = item["UserName"].Value<string>(),
UserID = item["Id"].Value<string>(),
};
public class UserDetails
{
public string UserName { get; set; }
public string UserID { get; set; }
}
Thanks,
Prem
RequestedObject is a property on the objects in the array, not the array itself.
var users =
from item in jsonObjects
let obj = item["RequestedObject"]
where (DateTime)obj["UpdateInformation"]["CreateDate"] >= previousRunTime
select new UserDetails
{
UserName = (string)obj["UserName"],
UserID = (string)obj["Id"],
};
you need only one line code if you are using LINQ to JSON
List<UserDetails> users = jsonArray.Where(i => (DateTime)i["RequestedObject"]
["UpdateInformation"]["CreateDate"] >= previousRunTime)
.Select(i => i["RequestedObject"].ToObject<UserDetails>()).ToList();
class
public class UserDetails
{
[JsonProperty("UserName")]
public string UserName { get; set; }
[JsonProperty("Id")]
public string UserID { get; set; }
}

LINQ searching a List that contains a Class with objects

I'm new at C#, I know how to do a LINQ search to a List with one field/type, but not with many types of an object. I created a List
List<Reader> results = new List<Reader>();
That contain this class:
public class Reader
{
public int ID { get; set; }
public string Name { get; set; }
public string Course { get; set; }
public int Grade { get; set; }
public Reader(int id, string name, string course, int grade)
{
ID = id;
Name = name;
Course = course;
Grade = grade;
}
}
I want to search it with LINQ and match the ID and Name of a user that entered the site.
If this two fields are the same I want to take from the List the users Course and Grade.
Any suggestion how to do it ?
A simple Where for condition(s) and Select for representation should do:
List<Reader> results = ...
var data = results
.Where(item => item.ID == userID && item.Name == userName)
// .OrderBy(item => item.Course) // uncomment if you want to order by course
.Select(item => $"Course: {item.Course} Grade: {item.Grade}");
foreach (var record in data)
Console.WriteLine(record);
First, let's assume that you have two variables that hold the values introduced by the user. Those variables are userName of type string and id of type integer. If you just want a variable that holds the course and the Grade you could select a new anonymous type and do the query like this:
var values= results
.Where(item => item.ID == userID && item.Name == userName)
.Select(item => new { Course = item.Course, Grade = item.Grade });
then you could use the values like:
values.Grades
values.Course
var Selecteduser = results.Where(x => x.Name == selectedname && x.ID == ID).ToList();
if (Selecteduser.Count != 0)
{
//found match ..(Selecteduser[0])
string selectedcourse = Selecteduser[0].Course;
int selectedgrade = Selecteduser[0].Grade;
}
else
{
//coudlnt find match
}

Filter Data based on same ID

I have a model class
public class Model
{
public string name { get; set; }
public string files { get; set; }
}
I have a controller class that populates the data from database into this model
List<Model> model = new List<Model>();
while (reader.Read()){
var om = new Model();
if (reader != null)
{
om.name = reader.GetString(0);
om.files = reader.GetString(1);
model.Add(om)
}
How can I filter and combine all files that have the similar first names?
I read about linq and tried this
var jm = om.name
.Where(o => om.name.Contains(o))
.Select() ;
This might work for you:
var grouped = model.GroupBy(m => m.name).ToArray();
This will create an object grouped of type IGrouping<string, Model>[] (array of IGrouping...)
.ToArray() is optional and if you remove it, you get IEnumerable<IGrouping<string, Model>>, but don't let the nested <> scare you.
The items in your original list are grouped by name, so the group will have Key property that will be the same for each element in the group.
To print the results, for example:
foreach(var group in grouped)
{
Console.WriteLine($"Printing group: {group.Key}");
foreach(var model in group)
{
Console.WriteLine($"\tName: {model.name}, File: {model.file}");
}
}
Note that each element in a group is a collection of your model objects.
Use debugger to see what that structure looks like and if you need more help - ask...
Change your Model
public class Model
{
public string name { get; set; }
public IList<string> files { get; set; }
}
Use a Dictionary.
var models = new Dictionary<string, Model>();
while (reader.Read())
{
var om = new Model();
if (reader != null)
{
var name = reader.GetString(0);
var file = reader.GetString(1);
if (models.Contains(name))
models[name].files.Add(file);
else
{
models.Add(name, new Model
{
name = name,
files = new List<string>{files}
});
}
}
}
Then you can pull out a combined list with LINQ:
var peopleFileLists = models.Select(x => x.Value).ToList();
foreach(var person in peopleFileLists)
{
foreach(var file in person.files)
Console.WriteLine(person.name + "-" + file);
}

Print linq query (select *l)

i need to print all rows from one table.
avoid placing: s.Adress+s.EmployeeID, etc
var query = from x
in bd.Employees
where x.City == "London" && x.TitleOfCourtesy == "Mr."
select x;
foreach(var s in query)
{
Console.WriteLine(s.Address+"---"+s.EmployeeID);
}
Console.WriteLine takes params so you can do this:
Console.WriteLine("{0}---{1}", s.Address, s.EmployeeID.ToString());
Or you can use C# 6.0 string interpolation (Note the dollar sign):
Console.WriteLine($"{s.Address}---{s.EmployeeID}");
EDIT
Since you mentioned in the comments:
I want to print all rows from each column from table Employees (Northwind db), without writing each of the columns names
You can do this, imagine you have a class:
public class One
{
public int Id { get; set; }
public string Name { get; set; }
}
You can:
// using System.Web.Script.Serialization;
var ser = new JavaScriptSerializer();
var one = ser.Serialize(new One() { Id = 1, Name = "George" });
Console.WriteLine(one);

convert string data array to list

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.

Categories

Resources