I have a list of objects Employee
public struct Employee
{
public string role;
public string id;
public int salary;
public string name;
public string address;
}
I want to get the object where the name and id property matches the condition.
I have tried using this:
List<Employee> EleList = new List<Employee>();
var employee= EleList.Find(sTag => sTag.id == 5b && sTag.name== "lokendra");
This is pretty time consuming because the list size is between 20000-25000.Is there any other way to retrieve the result. Please guide me on this.
You can speed this up by using an appropriate collection type, e.g. a Dictionary.
If the id of the Employee is unique, you can use it as the key in a dictionary of type Dictionary<string, Employee>. Searching would look like this:
Employee employee;
if(dict.TryGetValue("5b", out employee) && employee.name == "lokendra")
// employee found
else
// employee not found
Creating the dictionary would look like this:
dict = EleList.ToDictionary(x => x.id, x => x);
If it is not unique but reasonably focused (only a few employees with the same id), you can use it as a key in a dictionary of type Dictionary<string, List<Employee>>. Searching would look like this:
Employee GetEmployee(string id, string name)
{
List<Employee> employees;
if(!dict.TryGetValue(id, out employees))
return null;
return employees.FirstOrDefault(x => x.name == name);
}
Creating the dictionary would look like this:
dict = EleList.GroupBy(x => x.id)
.ToDictionary(x => x.Key, x => x.ToList());
Please note:
In both cases, you should create the dictionary only once and not for every search. So basically, instead of EleList you should have the dictionary.
showing what John Skeet in his comments to Daniel Hilgarth might envision
static ILookup<string, Employee> _employeeMap = EleList.ToLookup(x => x.id);
Employee GetEmployee(string id, string name)
{
return employeeMap[id].FirstOrDefault(x => x.Name == name);
}
You can try using Linq
yourList.Where(sTag => sTag.id == 5 && string.Equals(sTag.name, "lokendra", StringComparison.OrdinalIgnoreCase)).ToList();
Related
I'm really a newbie in ASP.NET, I have a table consists of 4 columns, id, name, address, and phone. I'd like to do a query select id, name from table x but I have no idea how to write it using LINQ in ASP.NET web API
public class rateperjamallController : ApiController
{
public double GET()
{
TeamDataContext db1 = new TeamDataContext();
var item = db1.Teams.Select(c => c);
var id = item.Select(a => a.id);
return id;}
}
}
Does anyone have any idea to help me since I am really a newbie?
Are you looking fora specific record in the dataset? If yes, you need to pass the id or name and create a query for that. For example, this is what you can do: (if you pass id as a parameter)
public class rateperjamallController : ApiController
{
public double GET(string id)
{
TeamDataContext db1 = new TeamDataContext();
return db1.Teams.Where(x => x.id == id)?.First();
}
}
What is the correct way to query Realm with LINQ where the query includes fields from other Realm objects? For example:
public class Department : RealmObject
{
[Primary Key]
public string UniqueId { get; set; }
}
public class Employee : RealmObject
{
[Primary Key]
public string Name { get; set; }
// Parent
public Department Department { get; set; }
}
Then I would expect to be able to do something like:
var employee = realm.All<Employee>().SingleOrDefault( e => e.Department.UniqueId == fooId && e.Name == fooName );
But this always returns no matches. Where() also returns no matches. However, eliminating the e.Department and searching only on employee name works fine but obviously does not scope to Department as intended.
This is with the latest Realm Xamarin 0.80.
What am I doing wrong?
Querying by nested RealmObjects attributes is not currently supported:
Just to clarify here, we don't yet support queries on related objects like this. We will in the future, but there is no timeline at the moment.
The following is also not currently supported:
var deptFilter = theRealm.ObjectForPrimaryKey<Department>("HR");
var employeesByDept = theRealm.All<Employee>().Where((Employee emp) => emp.Department == deptFilter & emp.Name == "StackOverflow");
The left-hand side of the And operator must be a direct access to a persisted property in Realm.
Unable to process '(emp.Department == value(Realm080.App+c__AnonStorey1).deptFilter)'.
You can do direct RealmObject equalities, just not in the same Linq expression, so break it down further into a sub-query.
Example of how I currently do it:
var deptFilter = theRealm.ObjectForPrimaryKey<Department>("HR");
var employeesByDept = theRealm.All<Employee>().Where((Employee emp) => emp.Department == deptFilter);
var employees = employeesByDept.Where((Employee emp) => emp.Name == "StackOverflow");
foreach (var emp in employees)
{
D.WriteLine(emp.Name);
}
Note: https://github.com/realm/realm-dotnet/issues/723
My Web API Controller has a method that retrieves a specified number of decriptions from a database table. There are duplicate descriptions with different IDs, so sometimes the query returns duplicates when I use SELECT TOP. I also added random (ORDER BY NEWID) to lessen the chances of getting dups but duplicates still get returned sometimes. I want to change the query to SELECT DISTINCT but not sure how to do that in my particular case. Using First() seems to be complicated here. Can anyone help? My method is below:
public List<String> GetRandomDescriptions(string cat, string subcat, int n)
{
using (MyContext ctx = new MyContext())
{
var temp = ctx.Interactions.Where(d => (d.Category.Equals(cat) && d.Subcategory.Equals(subcat)))).OrderBy(d=>Guid.NewGuid()).Take(n).Select(d=>d.Description).ToList();
return temp;
}
}
Here is my class:
[Table("[Records]")]
public class Interaction
{
[Key, Column("RECORD_ID")]
public string DescId { get; set;}
public string Category { get; set; }
public string Subcategory { get; set; }
public string Description{get; set;}
}
You can use something like this
var result = ctx.Interactions
.Where(d => d.Category == cat && d.Subcategory == subcat)
.Select(d => d.Description)
.Distinct()
.Take(n)
.ToList();
The key points are - first apply the filter, then select the description, then make it distinct and finally take the required number of items.
If you really need to pick a random items, then just insert your OrderBy before Take.
You don't need to do the funny OrderBy construct. Try something like this:
public List<String> GetRandomDescriptions(string cat, string subcat, int n)
{
using (MyContext ctx = new MyContext())
{
var temp = ctx.Interactions
.Where(d => d.Category.Equals(cat) && d.Subcategory.Equals(subcat)))
.Select(d=>d.Description)
.Distinct()
.ToList();
return temp;
}
}
I have a List<Product> contains properties of Bikes (Name, ProductName, Color, List Price). I'm struggling to figure out how to write a search function using LINQ. I'd like to find a name of Bike. Any suggest will be help me some ways.
Imagine that your name is taken from a variable called nameToSearch.
This is if you want to get the Product.
string nameToSearch = "BikeName";
List<Product> list = bikes.Where(x => x.Name == nameToSearch).ToList();
I assume you have the following Product class:
public class Product
{
public String Name { get; set; }
public String ProductName { get; set; }
public String Color { get; set; }
public String List { get; set; }
public String Price { get; set; }
}
You also mentioned you have your data in a List<Product>. I will give a demo name for it:
List<Product> myProductList = GetProductList();
// Where GetProductList() will create a new List<Product> and populate it.
String bikeNameFilter = GetNameFilter();
// You can chnage this by the string you want for filtering.
You can use the following to get your data:
List<Product> myFilteredProductList = (from p in myProductList
where p.Name = bikeNameFilter
select p;
).ToList()
Obviously you can change the filter you want to use to another property of your product. Finally to get the actual name, you can loop through the list you just got:
foreach (var p in myFilteredProductList)
{
Console.WriteLine(p.ProductName);
// Use this value wherever you want.
}
Take a look at a nuget package I have created
http://www.nuget.org/packages/NinjaNye.SearchExtensions
This will enable the following (and more) which will return results where the search term appears in any of the properties specified
var result = products.Search("searchTerm", p => p.Name, p => p.ProductName);
Performing a search against all string properties can be done as follows:
var result = products.Search("searchTerm");
Alternatively, you can perform an AND search where the search term exists in a set of properties as follows:
string searchTerm = "searchTerm";
var result = products.Search(searchTerm, p => p.Name)
.Search(searchTerm, p => p.ProductName);
For more information take a look at the projects GitHub page or my blog posts
UPDATE: don't forget the using directive...
using NinjaNye.SearchExtensions
How do I created the appropriate AbstractIndexCreationTask for the following scenario?
For a scenario of multiple blogs, how do I get the tags from specific blogs and the tag-count for these?
Members of interest for data-structure stored in RavenDB:
public class BlogPost {
public string BlogKey { get; set; }
public IEnumerable<string> Tags { get; set; }
/* ... */
}
The method I need to implement has the following signature:
public Dictionary<string, int> GetTagsByBlogs(string tag, params string[] blogKeys)
In normal LINQ I would write something like this:
var tags = from post in blogPosts
from tag in post.Tags
where blogKeys.Contains(post.BlogKey)
group tag by tag into g
select new {
Tag = g.Key,
Count = g.Count(),
};
But neither SelectMany or GroupBy are supported in RavenDB. I've tried different combinations for a map-reduce solution, but I can't figure out how to do this since the map and the reduce differ in data-structure.
How to create a tag cloud is described in the knowledge base of RavenDB.
In your case, you have to include the BlogKey in the index, especially in the group by clause:
public class Tags_Count : AbstractIndexCreationTask<BlogPost, Tags_Count.ReduceResult>
{
public class ReduceResult
{
public string BlogKey { get; set; }
public string Name { get; set; }
public int Count { get; set; }
}
public Tags_Count()
{
Map = posts => from post in posts
from tag in post.Tags
select new {
BlogKey = post.BlogKey,
Name = tag.ToString().ToLower(),
Count = 1
};
Reduce = results => from tagCount in results
group tagCount by new {
tagCount.BlogKey,
tagCount.Name } into g
select new {
BlogKey = g.Key.BlogKey,
Name = g.Key.Name,
Count = g.Sum(x => x.Count)
};
Sort(result => result.Count, SortOptions.Int);
}
}
Then query that index with the desired BlogKey:
var result = session.Query<Tags_Count.ReduceResult, Tags_Count>()
.Where(x => x.BlogKey = myBlogKey)
.OrderByDescending(x => x.Count)
.ToArray();
If you need to query for multiple blogs, you can try this query:
var tagsByBlogs = session.Query<Tags_Count.ReduceResult, Tags_Count>()
.Where(x => x.BlogKey.In<string>(blogKeys))
.OrderByDescending(x => x.Count)
.ToArray();
AFAIK that is as far as you can get with an index. You still have to aggregate the results on the client side as you did in your original question, except that you can skip the filtering on blogKeys:
var tags = from tag in tagsByBlogs
group tag by Name into g
select new {
Tag = g.Key,
Count = g.Count(),
};
Take a look at faceted search, you can specify the criteria at query time, like so:
var facetResults = s.Query<BlogPost>("BlogIndex")
.Where(x => x.BlogKey == "1" || x.BlogKey == "5" ...)
.ToFacets("facets/BlogFacets");
Then the grouping (and counts) is done on all the results that match the where clause.
Update You'll need an index that looks something like this:
from post in blogPosts
from tag in post.Tags
select new
{
post.BlogKey
Tag = tag
}