I try to fill dropdown value
in table column values are
KHI
ISL
LAHR
PARIS
LONDON
BCE-456
BXR-445
BET-567
TYU-112
OPL-456
NOW I dont want these
BXR-445
BET-567
TYU-112
OPL-456 etc etc
i want only city names not numbers
i try to populate throug this
var list = tea.tblRe.AsEnumerable()
.Where(x => !x.Region.Any(char.IsDigit))
.ToList();
so when i try above query this show only names but with repepation like this e.g.
KHI
ISL
KHI
LONDON
LONDON
LAHR
ISL
ISL
ISL
PARIS
LONDON
PARIS
PARIS
UPDATE
ok for this i i try to implement 'IEqualityComparer'
class tablregionclass : IEqualityComparer<tblRe>
{
#region IEqualityComparer<tblRe> Members
public bool Equals(tblRe x, tblRe y)
{
return x.Region.Equals(y.Region);
}
public int GetHashCode(tblRe obj)
{
return obj.Region.GetHashCode();
}
#endregion
}
and then when i implment this class like this
IEqualityComparer<tblRe_New> customComparer = new tablregionclass();
IEnumerable<tblRe_New> disntregions = collection.Distinct(customComparer);
this show error
Error 2 The name 'collection' does not exist in the current context
Error 1 Cannot implicitly convert type 'chart_project.tablregionclass' to 'System.Collections.Generic.IEqualityComparer<chart_project.tblReg_New>'. An explicit conversion exists (are you missing a cast?)
You can use char.IsDigit and Distinct(instead of GroupBy)
var res = tea.tblRegion_Uni.AsEnumerable()
.Where(x => !x.Region.Any(char.IsDigit))
.Select(x=> x.Region)
.Distinct()
.ToList();
if you need to bind to list of objects, then:
var res = tea.tblRegion_Uni.AsEnumerable()
.Where(x => !x.Region.Any(char.IsDigit))
.ToList();
I removed the select statment and Distinct!
For Distinct to work, you need to implement IEqualityComparer, or you can try this:
var res = tea.tblRegion_Uni.AsEnumerable()
.Where(x => !x.Region.Any(char.IsDigit))
.GroupBy(x=>x.Region)
.Select(x=>new {Region=x.Key, Value=x.Key})
.ToList();
Here I am returning an anonymous object with 2 props.
If you want to match which have a number, use RegExp:
var pattern = \[0-9]\g;
alert(pattern.test("BCE-456"));
Related
I am just not understanding the LINQ non-query syntax for GroupBy.
I have a collection of objects that I want to group by a single property. In this case Name
{ Id="1", Name="Bob", Age="23" }
{ Id="2", Name="Sally", Age="41" }
{ Id="3", Name="Bob", Age="73" }
{ Id="4", Name="Bob", Age="34" }
I would like to end up with a collection of all the unique names
{ Name="Bob" }
{ Name="Sally" }
Based on some examples I looked at I thought this would be the way to do it
var uniqueNameCollection = Persons.GroupBy(x => x.Name).Select(y => y.Key).ToList();
But I ended up with a collection with one item. So I though maybe I was over complicating things with the projection. I tried this
var uniqueNameCollection = Persons.GroupBy(x => x.Name).ToList();
Same result. I ended up with a single item in the collection. What am I doing wrong here? I am just looking to GroupBy the Name property.
var names = Persons.Select(p => p.Name).Distinct().ToList()
If you just want names
LINQ's GroupBy doesn't work the same way that SQL's GROUP BY does.
GroupBy takes a sequence and a function to find the field to group by as parameters, and return a sequence of IGroupings that each have a Key that is the field value that was grouped by and sequence of elements in that group.
IEnumerable<IGrouping<TSource>> GroupBy<TSource, TKey>(
IEnumerable<TSource> sequence,
Func<TSource, TKey> keySelector)
{ ... }
So if you start with a list like this:
class Person
{
public string Name;
}
var people = new List<Person> {
new Person { Name = "Adam" },
new Person { Name = "Eve" }
}
Grouping by name will look like this
IEnumerable<IGrouping<Person>> groups = people.GroupBy(person => person.Name);
You could then select the key from each group like this:
IEnumerable<string> names = groups.Select(group => group.Key);
names will be distinct because if there were multiple people with the same name, they would have been in the same group and there would only be one group with that name.
For what you need, it would probably be more efficient to just select the names and then use Distinct
var names = people.Select(p => p.Name).Distinct();
var uniqueNameCollection = Persons.GroupBy(x => x.Name).Select(y => y.Key).ToList();
Appears valid to me. .net Fiddle showing proper expected outcome: https://dotnetfiddle.net/2hqOvt
Using your data I ran the following code statement
var uniqueNameCollection = people.GroupBy(x => x.Name).Select(y => y.Key).ToList();
The return results were List
Bob
Sally
With 2 items in the List
run the following statement and your count should be 2.
people.GroupBy(x => x.Name).Select(y => y.Key).ToList().Count();
Works for me, download a nugget MoreLinq
using MoreLinq
var distinctitems = list.DistinctBy( u => u.Name);
I have an IEnumerable<MyObject> collection, with N MyObject elements.
MyObject is a class with a Title, a Description and an ID (as string).
I'd like to have my collection with distinct list of MyObject, due to the ID field.
So if 2 MyObject have got the same ID, one should be deleted (don't care which, I need unique ID).
How can I do it with LINQ?
Tried :
myList = myList.GroupBy(o => o.ID);
but seems I need a cast?
You can implement a custom IEqualityComparer<MyObject>. Then you can use Enumerable.Distinct to filter out duplicates.
class DistinctIdComparer : IEqualityComparer<MyObject> {
public bool Equals(MyObject x, MyObject y) {
return x.Id == y.Id;
}
public int GetHashCode(MyObject obj) {
return obj.Id.GetHashCode();
}
}
Now it's simple:
IEnumerable<MyObject> distinct = myObjects.Distinct(new DistinctIdComparer());
Or you can use Enumerable.GroupBy what is even simpler:
distinct = myObjects.GroupBy(o => o.ID)
.Select(g => g.First());
If you wants only unique id then you can try.
var uniqueIds = myObjects.Select(x=>x.ID).Distinct();
Or for Unique ID Objects
List<MyObject> objs = new List<MyObject> ();
myObjects.ForEach(x=>{
if(objs.Find(y=>y.ID == x.ID)== null)
objs.Add(x);
});
How can i add orderby to this:
return (from m in response["holder"].Children()
orderby m["name"]
select new SelectListItem
{
Text = m["name"].ToString(),
Value = m["name"].ToString()
}).ToList();
The problem is that the json returned in the response variable has a list of names, all of them have an uppercase first letter apart from one so they all get ordered fine except the one with the lower case which gets stuck at the bottom of the SelectListItem list.
Any ideas?
Thanks in advance..
EDIT:
Additional info - i am using JSON.NET to parse the json response. And the response variable is a JObject.
You'll need to normalize the data during your orderby. In my example I've chosen to use the ToUpperInvariant() method:
return (from m in response["holder"].Children()
orderby m["name"].ToUpperInvariant()
select new SelectListItem
{
Text = m["name"].ToString(),
Value = m["name"].ToString()
}).ToList();
I'm also assuming that m["name"] is already a String object. If it's not, change the line to:
orderby m["name"].ToString().ToUpperInvariant()
Maybe something like this:
return (from m in response["holder"].Children()
orderby m["name"].ToString().ToLower()
select new SelectListItem
{
Text = m["name"].ToString(),
Value = m["name"].ToString()
}).ToList();
When using the OrderBy method in the method syntax, you can specifiy a StringComparer. Passing a StringComparer that ignores casing solves your issue:
response["holder"]
.Children()
.OrderBy(m => m["name"], StringComparer.CurrentCultureIgnoreCase);
response["holder"]
.Children()
.OrderBy(m => m["name"] as String, StringComparer.CurrentCultureIgnoreCase)
.Select(m => new SelectedListItem
{
Text = m["name"].ToString(),
Value = m["name"].ToString())
})
.ToList();
return response["holder"].Children()
.Select(m => m.FirstCharToUpper())
.OrderBy(m => m["name"].ToString())
.Select(m => new SelectedListItem{
Text = m["name"].ToString(),
Value = m["name"].ToString()
})
.ToList();
static class Utility
{
public static string FirstCharToUpper(this string s)
{
return s.First().ToString().ToUpper() + string.Join("", s.Skip(1));
}
}
I'm using LINQ to manipulate a datatable. I have 3 columns - I would like group by one and then select the remaining 2 columns together. At the moment I have something like this
var query = reportDataTable.AsEnumerable()
.GroupBy(c => c["Code"])
.Select(g =>
new {
Code = g.Key,
Rank = g.Select(f => new
{ f["rank"],
f["Name"]}).ToArray()
});
but I get issues due to anonymous types. I know this syntax would work if I could reference the the column headers directly (in say a list or w/e). How can I get around this with DataTables? Cheers.
Edit:
Well I'd like to be able to reference the fields later when I come to populate the data into a different datatable:
foreach (var q in query)
{
DataRow df = dp.NewRow();
df["Code"] = q.Code;
foreach (var rank in q.Rank)
{
df[rank.name] = rank.rank;
}
dp.Rows.Add(df);
}
define your Rank fields, Also if you have a class for it, call related class constructor,
you can see this in bellow code, before ToArray.
var query = reportDataTable.AsEnumerable()
.GroupBy(c => c["Code"])
.Select(g =>
new { Code = g.Key, Rank =
g.Select(f => new { rank = f["rank"], name = f["Name"]})
.ToArray() });
This has been ruining my life for a few days now, time to ask...
I am using Entity Framework 4.0 for my app.
A Location (such as a house or office) has one or more facilities (like a bathroom, bedroom, snooker table etc..)
I want to display a checkbox list on the location page, with a checkbox list of facilities, with the ones checked that the location currently has.
My View Model for the facilities goes like this...
public class FacilityViewItem
{
public int Id { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
So when im passing the Location View Model to the UI, i want to pass a List<T> of facilities where T is of type FacilityViewItem.
To get the facilities that the location already has is simple - i make a query using Location.Facilities which returns an EntityCollection where T is of type Facility. This is because Facilities is a navigation property....
var facs = from f in location.Facilities
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name,
Checked = true
};
So here is where my problem lies - i want the rest of the facilities, the ones that the Location does not have.
I have tried using Except() and Any() and Contains() but i get the same error.
Examples of queries that do not work...
var restOfFacilities = from f in ctx.Facilities
where !hasFacilities.Contains(f)
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name
};
var restOfFacilities = ctx.Facilities.Except(facilitiesThatLocationHas);
var notFacs = from e in ctx.Facilities
where !hasFacilities.Any(m => m.FacilityId == e.FacilityId)
select new FacilityViewItem()
{
Id = e.FacilityId,
Name = e.Name
};
And the error i get with every implementation...
System.NotSupportedException was unhandled
Message=Unable to create a constant value of type 'Chapter2ConsoleApp.Facility'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
What am i overlooking here?
ironically enough i solved it in a matter of hours after i posted the question on here, after days of suffering.
The error is basically saying 'i dont know how to calculate what items are not included by comparing strongly typed objects. Give me a list of Ints or some simple types, and i can take care of it'.
So, first you need to get a list of the primary keys, then use that in the contains clause...
//get the primary key ids...
var hasFacilityIds = from f in hasFacilities
select f.FacilityId;
//now use them in the contains clause...
var restOfFacilities = from f in ctx.Facilities
where !hasFacilityIds.Contains(f.FacilityId)
select new FacilityViewItem()
{
Id = f.FacilityId,
Name = f.Name
};
The first query seems fine, but you need to compare the Ids:
var restOfFacilities = from f in ctx.Facilities
where !facs.Select(fac => fac.Id).Contains(f.Id)
select f;
I wanna see what's hasFacilities, anyway, as L2E shows, "Only primitive types ('such as Int32, String, and Guid') are supported in this context", so I suppose you must retrieve first the data and put into a collection of FacilityViewItem.
var restOfFacilities = ctx
.Facilities
.Where(f => !hasFacilities.Contains(f))
.Select(f => new { f.FacilityId, f.Name })
.ToList()
.Select(f => new FacilityViewItem {
Id = f.FacilityId,
Name = f.Name
});
var notFacs = ctx
.Facilities
.Where(e => !hasFacilities.Any(m => m.FacilityId == e.FacilityId))
.Select(e => new { e.FacilityId, e.Name })
.ToList()
.Select(e => new FacilityViewItem {
Id = e.FacilityId,
Name = e.Name
});
hope it helps