How to get distinct records from a list - list

I have a list of type Myclass
List<Myclass> liSubjectIdDetail = new List<Myclass>();
where Myclass looks like
public class Myclass
{
public Nullable<decimal> SubjectId { get; set; }
public string SubjectName { get; set; }
}
I am adding records into liSubjectIdDetail from a table
foreach (decimal Id in VarCEMSIdDetail)
{
liSubjectIdDetail.AddRange(db.Stt.MyTable.Where(x => x.Id == Id).Select(x => new Myclass { SubjectId = x.SubjectId, SubjectName = x.SubjectName }).ToList());
}
where Id contains a list of certain Ids on the basis of which records I fetch.
Now I want to get only distinct records in this list.
I have tried it with hashtable in place of List
and I also tried
liSubjectIdDetail= liSubjectIdDetail.Distinct().ToList();
but this too, is not working. Please give me a better solution.
Thanks in advance

Try this extension method
public static class IEnumerableExtensions {
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
Usage:
liSubjectIdDetail= liSubjectIdDetail.DistinctBy(s => s.SubjectName).ToList();

Related

How to display grouped list of values in Xamarin?

I am trying to display grouped list of songs, which I get from server. Songs are grouped in sets according to their first letter. I've created two classes in this purpose SongSet and Song.
public class SongSet
{
public string FirstCharacter { get; set; }
public List<Song> ListOfSongs { get; set; } = new List<Song>();
public SongSet(string firstChar)
{
this.FirstCharacter = firstChar;
}
}
public class Song
{
public string SongTitle { get; set; }
public Song(string title)
{
this.SongTitle = title;
}
}
After received list from server I put it to list of SongSet objects.
public static List<SongSet> ListOfSongsFromServer { get; set; } = new List<SongSet>();
And here my code to display a whole list.
ListView listView = new ListView
{
IsGroupingEnabled = true,
GroupDisplayBinding = new Binding("FirstCharacter"),
ItemsSource = PlayerPageVM.ListOfSongsFromServer,
ItemTemplate = new DataTemplate(() =>
{
Label titleLabel = new Label();
titleLabel.SetBinding(Label.TextProperty, "SongTitle");
return new ViewCell
{
View = new StackLayout
{
Padding = new Thickness(0, 5),
Orientation = StackOrientation.Horizontal,
Children =
{
new StackLayout
{
VerticalOptions=LayoutOptions.Center,
Spacing=0,
Children =
{
titleLabel
}
}
}
}
};
})
};
this.Content = new StackLayout
{
Children =
{
listView
}
};
After build application I've received only list with first letters but without song titles uder them. Can anyone help me how to achievie this?
You want to display grouped list of songs, you could use CollectionView. Because it provides the easy way to show Group data.
Display grouped data:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
...
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And the problem of mode data could refer to document to make SongSet inherit from Lsit<Song> to generate a grouped data.
public class SongSet : List<Song>
{
public string FirstCharacter { get; set; }
public SongSet(string firstChar,List<Song> ListOfSongs): base(ListOfSongs)
{
this.FirstCharacter = firstChar;
}
}

How to get distinct values from 2 different columns in the same list

So as you can see from the code bellow i have a list object named Matches, from which i would like to get a single list of the distinct teams, both from HomeTeam and AwayTeam. I'm trying to use LINQ and i can get a list of distinct teams if i only use HomeTeam parameter or AwayTeam parameter but not both together.
Thank you.
public class Match
{
public int ID { get; set; }
public string Country { get; set; }
public string Championship { get; set; }
public string Seasson { get; set; }
public DateTime MatchDate { get; set; }
public string HomeTeam { get; set; }
public int HomeScore { get; set; }
public int AwayScore { get; set; }
public string AwayTeam { get; set; }
}
private List<Match> Matches;
Matches = dataAccess.GetAllMatches();
I'm Trying to do something like that:
result = Matches.Select(HomeTeam, AwayTeam).Distinct().ToList();
At the risk that this smells like homework, a hint rather than code. Get your Home teams, Union your Away teams and apply a Distinct to the result.
So i finally come up with this solution.
Notice that now i need also to get not only the team but the country which the team belongs to.
public class Team
{
public string Name { get; set; }
public string Country { get; set; }
}
So Union really do the job here but since now i need to get it as an anonymous type... here is the code:
List<Team> teams = new List<Team>();
var result = Matches.Select(x => new { Name = x.HomeTeam, Country = x.Country }).Union(Matches.Select(x => new { Name = x.AwayTeam, Country = x.Country })).ToList();
foreach (var record in result)
{
teams.Add(new Team { Name = record.Name, Country = record.Country });
}
return teams;
I would prefer this way:
List<Team> teamsResult = Matches.Select(x => new Team { Name = x.HomeTeam, Country = x.Country }).Union(Matches.Select(x => new Team { Name = x.AwayTeam, Country = x.Country })).ToList();
But this way get duplicates so i will stick with the first example for now.
Do you think it is the more elegant way to go?
Thank you.
You can take advantage of GroupBy, like this:
IEnumerable<Team> teams = Matches.GroupBy(m => new { m.AwayTeam, m.HomeTeam, m.Country })
.Select(
g =>
new[]
{
new Team {Country = g.Key.Country, Name = g.Key.AwayTeam},
new Team {Country = g.Key.Country, Name = g.Key.HomeTeam}
})
.SelectMany(x => x)
.GroupBy(t => new { t.Name, t.Country })
.Select(g => new Team { Name = g.Key.Name, Country = g.Key.Country });

How to convert a dynamic list into list<Class>?

I'm trying to convert a dynamic list into a list of class-model(Products). This is how my method looks like:
public List<Products> ConvertToProducts(List<dynamic> data)
{
var sendModel = new List<Products>();
//Mapping List<dynamic> to List<Products>
sendModel = data.Select(x =>
new Products
{
Name = data.GetType().GetProperty("Name").ToString(),
Price = data.GetType().GetProperty("Price").GetValue(data, null).ToString()
}).ToList();
}
I have tried these both ways to get the property values, but it gives me null errors saying these properties doesn't exist or they are null.
Name = data.GetType().GetProperty("Name").ToString(),
Price = data.GetType().GetProperty("Price").GetValue(data,
null).ToString()
This is how my Model-class looks like:
public class Products
{
public string ID { get; set; }
public string Name { get; set; }
public string Price { get; set; }
}
Can someone please let me know what I'm missing? thanks in advance.
You're currently trying to get properties from data, which is your list - and you're ignoring x, which is the item in the list. I suspect you want:
var sendModel = data
.Select(x => new Products { Name = x.Name, Price = x.Price })
.ToList();
You may want to call ToString() on the results of the properties, but it's not clear what's in the original data.

Lambda Expression to get records from list in a list

I have a class as following:
public class Wrapper
{
public Wrapper();
public Class1 c1 { get; set; }
public List<Class2> lstC2 { get; set; }
}
where Class2 is :
public class Class2
{
public DateTime date1 { get; set; }
}
and I get the list of objects of Wrapper class by some method
List<Wrapper> lstWrap = SomeMethod();
Now I want to remove All the records from lstWrap where date1 is less than today for any record in lstC2 using lambda expression. I tried using RemoveAll function but could not meet the results.
Thank You.
in these situations I would use .All() or .Any()
var lts = new List<Wrapper>();
var res = lts.Where (l => l.lstC2.All(d => d.date1 >= DateTime.Now));
EDIT:
To remove all I would still use the .Any()
lstWrap.RemoveAll(l => l.lstC2.Any(a => a.date1 < DateTime.Now));
if you want to delete the item with at least one date which less than today,use:
lstWrap.RemoveAll(l=>l.lstC2.Count(d=>d.date1<DateTime.Today)>0);

How to create a list dynamically from a class name (which is passed as argument) and return the list in c#.net

How to create a list dynamically from a class name (which is passed as an argument) and return the list in C#.
Below code may not work. I have posted it to give an idea:
public T ConvertDataSetToList<T>(DataSet _ds, String tableName, string className)
{
Type classType=Type.GetType(className);
List<T> newList = new List<T>();
//System.Activator.CreateInstance(Type.GetType(className));
try
{
Details _Details;
for (int iRowCount = 0; iRowCount < _ds.Tables[tableName].Rows.Count; iRowCount++)
{
_Details = FillDTO(_ds.Tables[tableName].Rows[iRowCount]);
newList.Add(_msDetails);
}
}
catch (Exception ex) { }
return newList;
}
You can dot it with some basic mapping stuff.
//Maps a dataset
public List<T> MapDataSet<T>(DataSet anyDataset
, string tablename) where T : new()
{
return MapDataTable<T>(anyDataset.Tables[tablename]);
}
// Maps a datatable
public List<T> MapDataTable<T>(DataTable table) where T : new()
{
List<T> result = new List<T>();
foreach(DataRow row in table.Rows)
{
result.Add(MapDataRow<T>(row));
}
return result;
}
// maps a DataRow to an arbitrary class (rudimentary)
public T MapDataRow<T>(DataRow row) where T: new()
{
// we map columns to class properties
Type destinationType = typeof(T);
// create our new class
T mappedTo = new T();
// iterate over the columns
for(int columnIndex=0;columnIndex<row.ItemArray.Length;columnIndex++)
{
// get a matching property of our class
PropertyInfo fieldTo = destinationType.GetProperty(
row.Table.Columns[columnIndex].ColumnName );
if (fieldTo !=null)
{
// map our fieldvalue to our property
fieldTo.SetValue(mappedTo, row[columnIndex], new object[] {});
}
else
{
// sorry, field doens't match any property on class
}
}
return mappedTo;
}
Here is basic test app to demonstrate its usage
void Main()
{
DataTable dt = new DataTable("hello");
dt.Columns.Add("foo");
dt.Columns.Add("bar");
dt.Columns.Add("foobar");
DataRow row = dt.NewRow();
row[0]="blah1";
row[1] ="two";
row[2] = "fb1";
dt.Rows.Add(row);
row = dt.NewRow();
row[0]="apples";
row[1] ="pears";
row[2] = "duh";
dt.Rows.Add(row);
List<DTO> list = MapDataTable<DTO>(dt);
List<SecondDTO> list2 = MapDataTable<SecondDTO>(dt);
}
// sample DTO object
public class DTO
{
public string foo { get; set;}
public string bar { get; set; }
}
// another sample DTO object
public class SecondDTO
{
public string foo { get; set;}
public string foobar { get; set; }
}