Subtract two properties in list with eachother - c#

I want to get the difference between two integers, in this case "Age" - subtract them.
Here my class and my list. I want to, with a method, take the age from Robin and Sara and show the age difference. Is this possible with LINQ or..?
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class LinqQuery
{
private readonly List<Person> _persons = new List<Person>
{
new Person {FirstName = "Robin", LastName = "Blixt", Age = 29},
new Person {FirstName = "Sara", LastName = "Johansson", Age = 44}
};
public IEnumerable<Person> GetAll()
{
return _persons;
}
public void difference()
{
?????
Console.ReadKey();
}
}
Thanks in advance.

You can use lambda expression to find specified index if FirstName is youre key and you have more items than two.
Please note that I did not check any erros (empty list etc.)
public void diff()
{
int indxRobin = lst.FindIndex((item) => { return item.FirstName == "Robin"});
int indxSara = lst.FindIndex((item) => { return item.FirstName == "Sara"});
return lst[indxRobin].Age - lst[indxSara].Age;
}

Using a cross-join you could calculate the age difference for all permutations in the list.
Of course, this is very crude and gives all duplicates, but it's easy from there to remove the duplicates in the query.
public void Difference()
{
var ageDifferences = from p1 in _persons
from p2 in _persons
select new
{
P1FullName = p1.FirstName + " " + p1.LastName,
P2FullName = p2.FirstName + " " + p2.LastName,
AgeDifference = Math.Abs(p1.Age - p2.Age)
};
foreach (var item in ageDifferences)
{
Console.Out.WriteLine("{0} and {1} have {2} years of age difference.", item.P1FullName, item.P2FullName, item.AgeDifference);
}
Console.ReadKey();
}

Thanks, #Tim Schmelter for the suggestion :)
public void difference()
{
int sara= _persons.FirstOrDefault(p=>p.FirstName=="Sara").Age;
int robin=_persons.FirstOrDefault(p=>p.FirstName=="Robin").Age;
int difference= Math.abs(sara-robin);
Console.ReadKey();
}

Related

LINQ to Get All heirerichal children

I have been digging this quite a while.
public class Person
{
public string Name { get; set; }
public string Age { get; set; }
public List<Person> Children { get; set; }
}
I want a single LINQ query to find out "All the persons whose Age > 4 in this collection".
Note: You have to traverse Collection of Person + Collection of Children, so each children object will have a collection of Person till Children becomes null.
First i can't understand why all your properties private and Age is not int type. So my class looks like this:
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
public List<Person> Childrens { get; set; }
}
Note partial word. This word will allow you to place your class logic in separate files and this could be usefull when you creating some custom logic in class.
Then I simply create this method in different file:
public partial class Person
{
public Person GetPersonWithChindren(int maxAge)
{
return new Person
{
Age = this.Age,
Name = this.Name,
Childrens = this.Childrens != null
? this.Childrens
.Where(x => x.Age < maxAge)
.Select(x => x.GetPersonWithChindren(maxAge)) //this line do recursive magic
.ToList()
: null
};
}
}
As you can see this method checking Age of each child and if Age is ok then it checks next level of hierarchy untill Childrens is null.
So you can use it like this:
var person = new Person()
{
//initialisation of your collection here
}
//result will contains only nodes where Person have age < 4 and Childs that have age < 4
var result = person.GetPersonWithChindren(4);
Note that this solution will work normal with linqToEntities. But if you using LinqToSQL this expression produces query to DB on each Person entity. So if you have many Persons and deep hierarhy it will costs you a lot of machine time. In that case you should to write stored procedure with CTE instead of LinQ query.
UPDATE:
You even can write more general solution with a help of Func<T> class like this:
public partial class Person
{
public Person GetPersonWithChindren(Func<Person, bool> func)
{
return new Person
{
Age = this.Age,
Name = this.Name,
Childrens = this.Childrens != null
? this.Childrens
.Where(x => func(x))
.Select(x => x.GetPersonWithChindren(func))
.ToList()
: null
};
}
}
And then you can use it like this:
var result = person.GetPersonWithChindren(x => x.Age < 4);
You always can change your criteria now where you want to use your function.
Create a visitor. In this example by implementing a helper class:
public static class Helpers
public static IEnumerable<Person> GetDescendants(this Person person)
{
foreach (var child in person.Children)
{
yield return child;
foreach (var descendant in child.GetDescendants())
{
yield return descendant;
}
}
}
this is one of the times where the "yield return many" would be useful.
If you're ensuring that .Children is automatically created, then this works:
Func<Person, Func<Person, bool>, Person> clone = null;
clone = (p, f) => f(p) ? new Person()
{
Name = p.Name,
Age = p.Age,
Children = p.Children.Select(c => clone(c, f)).Where(x => x != null).ToList(),
} : null;
var olderThan4 = clone(person, p => p.Age > 4);
Yes, that's it. Effectively three lines.
If you start with this data:
var person = new Person()
{
Name = "Fred", Age = 30,
Children = new List<Person>()
{
new Person() { Name = "Bob", Age = 7, },
new Person() { Name = "Sally", Age = 3, }
},
};
...then you get this result:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
private List<Person> _children = null;
public List<Person> Children
{
get
{
if (_children == null)
{
_children = new List<Person>();
}
return _children;
}
set
{
_children = value;
}
}
}

What is the best way to display List items on the console based on the value of the items' properties?

I have a List that cointains some objects that have 2 string and 2 int properties. I would like to be able to display all the 4 properties of an object based on the content of its first property.
For example: I want to display all the data of all the items of the list that's first property is "Mozart".
Thanks in advance!
I have a really basic class that has 4 properties, 2 strings, and 2 ints, all of them have their respective getters/ setters set to public.
I also have a List that contains some of these objects.
My code looks like this.
Console.WriteLine("Give in the name you want to search for!");
string s = Console.ReadLine();
After this, I would like to check if the first property is "s", and if it is, display all of that given object's data on the screen.
Have a look at this and let me know if you're stuck with any of it :)
void Main()
{
List<Music> myMusic = new List<Music>
{
new Music
{
Artist = "Mozart",
Album = "Mozarts amazing album",
TotalTracks = int.MaxValue,
Etc = int.MinValue
},
new Music
{
Artist = "Foo",
Album = "Bar",
TotalTracks = int.MaxValue,
Etc = int.MinValue
},
};
var mozartsMusic = myMusic.Where(music => music.Artist == "Mozart")
.ToList();
mozartsMusic.ForEach(Console.WriteLine);
}
public class Music
{
public string Artist { get; set; }
public string Album { get; set; }
public int TotalTracks { get; set; }
public int Etc { get; set; }
public override string ToString()
{
return string.Join("\n",this.GetType().GetProperties().Select(p=>string.Format("{0} {1}", p.Name, p.GetValue(this))));
}
}
Something like this would do the trick:
class Datum
{
public string Composer { get; set; }
///wharever other proerties you need
public string DisplayOutput()
{
return this.Composer //+ however you want it displayed
}
}
class Program
{
static void Main(string[] args)
{
List<Datum> data = new List<Datum>();
foreach (var outputLine in data.Where(d => d.Composer == "Mozart").Select(d=>d.DisplayOutput())
{
Console.WriteLine(outputLine);
}
}
}
That should be a possible way to do so:
class Composer
{
public Composer( string lastName, string firstName, int year, int month )
{
LastName = lastName;
FirstName = firstName;
YearOfBirth = year;
MonthOfBirth = month;
}
public string LastName { get; set; }
public string FirstName { get; set; }
public int YearOfBirth { get; set; }
public int MonthOfBirth { get; set; }
public override string ToString()
{
return string.Format( "{0} {1} {2} {3}", LastName, FirstName, YearOfBirth.ToString(), MonthOfBirth.ToString() );
}
}
class Program
{
private static new List<Composer> composerList = new List<Composer>();
static void Main( string[] args )
{
composerList.Add( new Composer( "Mozart", "Wolfgang", 1756, 1 ) );
composerList.Add( new Composer( "Vivaldi", "Antonio", 1678, 3 ) );
Console.WriteLine( "Please enter a name you want to search for!" );
string name = Console.ReadLine();
ShowComposerData( name );
}
private static void ShowComposerData( string name )
{
foreach( Composer comp in composerList )
{
if( comp.LastName == name )
{
Console.WriteLine( comp.ToString() );
}
}
}
}

c# : how to read from specific index in List<person>

I have a class of persons and list collection as list contains all the values of person class
such as :
List ilist has 2 values [0]={firstname,lastname} . [1]={firstname2,lastname2}
now when i am iterating into the list i am able to print the list but i want to change the value of some parts of my list e.g in index 1 if i want to change the value of firstname2 to firstname3 i am not able to do it . Can anyone tell me how to print the list and then on that index changing any value of the index , i.e. firstname and secondname variable in the person class so that i can update my values
Thanks
According to the docs on msdn you can use the familiar index operator (like on what you use on arrays). So myList[1].lastname = "new last name"; should do it for you.
Docs are here; http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx
Keep in mind you need to do bounds checking before access.
I came here whilst searching for access specific index in object array values C# on Google but instead came to this very confusing question. Now, for those that are looking for a similar solution (get a particular field of an object IList that contains arrays within it as well). Pretty much similar to what the OP explained in his question, you have IList person and person contains firstname, lastname, cell etc and you want to get the firstname of person 1. Here is how you can do it.
Assume we have
IList<object> myMainList = new List<object>();
myMainList.Add(new object[] { 1, "Person 1", "Last Name 1" });
myMainList.Add(new object[] { 2, "Person 2", "Last Name 2" });
At first, I though this would do the trick:
foreach (object person in myMainList)
{
string firstname = person[1].ToString() //trying to access index 1 - looks right at first doesn't it??
}
But surprise surprise, C# compiler complains about it
Cannot apply indexing with [] to an expression of type 'object'
Rookie mistake, but I was banging my head against the wall for a bit. Here is the proper code
foreach (object[] person in myMainList) //cast object[] NOT object
{
string firstname = person[1].ToString() //voila!! we have lift off :)
}
This is for any newbie like me that gets stuck using the same mistake. It happens to the best of us.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
List<Person> list = new List<Person>();
Person oPerson = new Person();
oPerson.Name = "Anshu";
oPerson.Age = 23;
oPerson.Address = " ballia";
list.Add(oPerson);
oPerson = new Person();
oPerson.Name = "Juhi";
oPerson.Age = 23;
oPerson.Address = "Delhi";
list.Add(oPerson);
oPerson = new Person();
oPerson.Name = "Sandeep";
oPerson.Age = 24;
oPerson.Address = " Delhi";
list.Add(oPerson);
int index = 1; // use for getting index basis value
for (int i=0; i<list.Count;i++)
{
Person values = list[i];
if (index == i)
{
Console.WriteLine(values.Name);
Console.WriteLine(values.Age);
Console.WriteLine(values.Address);
break;
}
}
Console.ReadKey();
}
}
class Person
{
string _name;
int _age;
string _address;
public String Name
{
get
{
return _name;
}
set
{
this._name = value;
}
}
public int Age
{
get
{
return _age;
}
set
{
this._age = value;
}
}
public String Address
{
get
{
return _address;
}
set
{
this._address = value;
}
}
}
}
More information on your requirement / why you are accessing the list this way might help provide a better recommendation on approach but:
If you want to use your list in this way frequently an Array or ArrayList may be a better option.
That said, if your specific issue is determining the current element you want to change's ID you can use IndexOf(). (note this will loop the array to find the object's position)
If you just know the index of the element, you can reference as both you and #evanmcdonnal describe.
Lists can be modified directly using their indexer.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
var list = new List<Person>
{
new Person
{
FirstName = "Bob",
LastName = "Carlson"
},
new Person
{
FirstName = "Elizabeth",
LastName = "Carlson"
},
};
// Directly
list[1].FirstName = "Liz";
// In a loop
foreach(var person in list)
{
if(person.FirstName == "Liz")
{
person.FirstName = "Lizzy";
}
}
I do not see where you can meet the problem:
public class Persons
{
public Persons(string first, string last)
{
this.firstName = first;
this.lastName = last;
}
public string firstName { set; get; }
public string lastName { set; get; }
}
...
List<Persons> lst = new List<Persons>();
lst.Add(new Persons("firstname", "lastname"));
lst.Add(new Persons("firstname2", "lastname2"));
for (int i = 0; i < lst.Count; i++)
{
Console.Write("{0}: {2}, {1}", i, lst[i].firstName, lst[i].lastName);
if (i == 1)
{
lst[i].firstName = "firstname3";
lst[i].lastName = "lastname3";
Console.Write(" --> {1}, {0}", lst[i].firstName, lst[i].lastName);
}
Console.WriteLine();
}
}
Output:
0: lastname, firstname
1: lastname2, firstname2 --> lastname3, firstname3

Convert arraylist to a list of dictionaries?

Does somebody know how to convert an arraylist to a list of dictionaries?
What do I have? I have an ArrayList (list) with a lot of strings:
foreach (string s in list)
{
Console.WriteLine(s);
}
output:
klaus
male
spain
lissy
female
england
peter
male
usa
...
As we see there is an order. The first entry is a NAME, second GENDER, third COUNTRY and then again NAME, GENDER... and so on.
Now for clarity I would like to store these attributes in a List of Dictionaries. Every List entry should be 1 Dictionary with these 3 Attributes. Is this a good idea? Whats the easiest way? I just search something to store this list in a better looking collection that is later easiert to handle. I have this:
List<Dictionary<string, string>> dlist = new List<Dictionary<string, string>>();
const int separate = 3;
foreach (string s in list)
{
//add list entries to dlist?
}
No it's not a good idea. Define a class.
At least something like this:
class Person
{
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
Even better would be to use an enum for Gender, and possibly a class (built-in or custom) for the country.
Anyway, to populate a collection with the above class, you'd use something like:
List<Person> result = new List<Person>();
for (int i = 0; i < list.Count; i += 3) {
result.Add(
new Person { Name = list[i], Gender = list[i+1], Country = list[i+2] });
}
Note that this loop lacks error checking on the count of items in the list, which should be a multiple of three.
enum Gender
{
Male = 0,
Female = 1
}
class Person
{
public string Name { get; set; }
public Gender Gender { get; set; }
public string Country { get; set; }
public Person(string name, Gender gender, string country)
{
this.Name = name;
this.Gender = gender;
this.Country = country;
}
}
Usage:
List<Person> persons = new List<Person>();
Person person;
for (int i = 0; i < list.Count; i += 3) {
{
person = new Person(list[i], (Gender)Enum.Parse(typeof(Gender), list[i+1], true), list[i+2]);
persons.add(person);
}
I would recommend using a class to encapsulate your entry:
class Entry
{
public String Name { get; set; }
public String Gender { get; set; }
public String Country { get; set; }
}
Then add to a list of Entrys
List<Entry> elist = new List<Entry>();
for (int i = 0; i < list.Count; i += 3)
{
var ent = new Entry() { Name = list[i],
Gender = list[i+1],
Country = list[i+2]};
elist.Add(ent);
}
Or you could use Tuples:
List<Tuple<string, string, string>> tlist =
new List<Tuple<string, string, string>>();
for (int i = 0; i < list.Count; i += 3)
{
Tuple<string,string, string> ent
= new Tuple<string,string,string>(list[i], list[i+1], list[i+2]);
tlist.Add(ent);
}
the simplest way to implement that - it's create a new class for representing someone in you list with 3 props:
public class Someone {
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
And than you can fill your destination list with Someone entries:
List<Someone> dList = new List<Someone>();
for(int i = 0; i < list.Count; i += 3)
dList.Add(new Someone() { Name = list[i], Gender = list[i+1], Country = list[i+2] });
p.s. this code may contain errors because I don't have access to computer with VS installed.
You may have a class to hold the data like:
public class Info
{
public string Name { get; set; }
public string Gender { get; set; }
public string Country { get; set; }
}
then you can have a dictionary like this
Dictionary<int, Info> infoDict = new Dictionary<int, Info>();
then you can start reading and prepare the dictionary.
var listSrc = new List<string>
{
"klaus",
"male",
"spain",
"lissy",
"england",
"female",
"peter",
"usa",
"male",
};
var dlist = new List<Dictionary<string, string>>();
for (var i = 0; i < listSrc.Count; i++)
{
var captions = new List<string>
{
"Name",
"Gender",
"Country"
};
var list = listSrc.Take(3).ToList();
listSrc.RemoveRange(0, 3);
dlist.Add(list.ToDictionary(x => captions[list.IndexOf(x)], x => x));
}
Its simple. You are working for a class that contains three data variables named :
String name;
String gender;
String country;
So make a class that contains all three of these variables. As for eg:
class Dictnary
{
public Dictnary(String nameFromCall, String genderFromCall, String countryFromCall)
{
this.name = nameFromCall;
this.gender = genderFromCall;
this.country = countryFromCall;
}
}
To answer the question in the title, this is probably the most succinct way to do the conversion:
for (int i = 0; i < list.Count; i += 3) {
dlist.Add(new Dictionary<string, string>() {
{ "name", (string)list[i] },
{ "gender", (string)list[i+1] },
{ "country", (string)list[i+2] }
});
}
(If you switch from an ArrayList to a List<string>, you can drop the (string) cast.)
That said, unless you really need a dictionary for some technical reason, your problem is better solved using one of the class-based approaches suggested in the other answers.

How to use IndexOf() method of List<object>

All the examples I see of using the IndexOf() method in List<T> are of basic string types. What I want to know is how to return the index of a list type that is an object, based on one of the object variables.
List<Employee> employeeList = new List<Employee>();
employeeList.Add(new Employee("First","Last",45.00));
I want to find the index where employeeList.LastName == "Something"
int index = employeeList.FindIndex(employee => employee.LastName.Equals(somename, StringComparison.Ordinal));
Edit: Without lambdas for C# 2.0 (the original doesn't use LINQ or any .NET 3+ features, just the lambda syntax in C# 3.0):
int index = employeeList.FindIndex(
delegate(Employee employee)
{
return employee.LastName.Equals(somename, StringComparison.Ordinal);
});
public int FindIndex(Predicate<T> match);
Using lambdas:
employeeList.FindIndex(r => r.LastName.Equals("Something"));
Note:
// Returns:
// The zero-based index of the first occurrence of an element
// that matches the conditions defined by match, if found;
// otherwise, –1.
you can do this through override Equals method
class Employee
{
string _name;
string _last;
double _val;
public Employee(string name, string last, double val)
{
_name = name;
_last = last;
_val = val;
}
public override bool Equals(object obj)
{
Employee e = obj as Employee;
return e._name == _name;
}
}
Sorry, one more for good measure :)
int index = employees.FindIndex(
delegate(Employee employee)
{
return employee.LastName == "Something";
});
Edit: - Full Example in .NET 2.0 Project.
class Program
{
class Employee { public string LastName { get; set; } }
static void Main(string[] args)
{
List<Employee> employeeList = new List<Employee>();
employeeList.Add(new Employee(){LastName="Something"});
employeeList.Add(new Employee(){LastName="Something Else"});
int index = employeeList.FindIndex(delegate(Employee employee)
{ return employee.LastName.Equals("Something"); });
Console.WriteLine("Index:{0}", index);
Console.ReadKey();
}
}
I prefer like this
private List<Person> persons = List<Person>();
public PersonService()
{
persons = new List<Person>() {
new Person { Id = 1, DOB = DateTime.Today, FirstName = "Pawan", LastName = "Shakya" },
new Person { Id = 2, DOB = DateTime.Today, FirstName = "Bibek", LastName = "Pandey" },
new Person { Id = 3, DOB = DateTime.Today, FirstName = "Shrestha", LastName = "Prami" },
new Person { Id = 4, DOB = DateTime.Today, FirstName = "Monika", LastName = "Pandey" },
};
}
public PersonRepository.Interface.Person GetPerson(string lastName)
{
return persons[persons.FindIndex(p=>p.LastName.Equals(lastName, StringComparison.OrdinalIgnoreCase))];
}
The answer is for those coming here to know why IndexOf()
doesn't work.
Your class must override Equals method of object possessing the following declaration.
public override bool Equals(object obj)

Categories