understanding an expression: selection from list - dart

I have come across at this statement, and as a newby at dart, I cant figure out how it works, and how exactly does it selection from the List, please help!
var playersL=players.map<Player>((String _playerID) =>
store.state.players.players.firstWhere((Player _player) => _player?.id == _playerID)
)

Depending on what you are doing with playersL, it is not going to work as expected since the expression returns a Iterable<Player>. I guess the L means you want a List so you should put a toList() at the end:
var playersL = players
.map<Player>((String _playerID) => store.state.players.players
.firstWhere((Player _player) => _player?.id == _playerID))
.toList();
But what the code are doing is the following:
Go though players (which I guess are List<String> and convert each String into a Player object.
To do so, we check (for each String), store.state.players.players (which I guess are List<Player>, and finds the first Player object which have an id which the same as the String coming from players.

Related

Lucene search to match exact element in Umbraco array

I'm trying to search Umbraco (v10) tags, which are stored as an array. Regardless of whether they are stored in CSV or JSON, I can't force an exact match.
For example, one article has tags containing "foo bar", while a second article has tags containing "foo".
If I use Lucene to search for foo, I get both articles returned. I do not want to match "foo bar".
This is my code:
IBooleanOperation query = _externalIndex.Searcher
.CreateQuery("content", BooleanOperation.And)
.NodeTypeAlias(modelTypeAlias)
.And()
//.Field("tags", tag);
.NativeQuery($"tags:\"{tag}\"");
I have tried using NativeQuery, wrapping my tag in quotes, using regex to match start/end of the string, using parenthesis to indicate a set of matches.
I cannot identify a way to isolate an exact match.
While your question is slightly different the this one, the answer is basically the same.
If you want the index to be based on the whole field rather then the individual words then you need to make sure the field is indexed as a StringField rather then a TextField.
String fields are not tokenized.
RonC's answer pointed me in the right direction, but it was more complicated than that.
I needed to split the JSON array of tags into individual elements, using the TransformingIndexValues event handler, and store them in a new field tagsSplit:
private void TransformTagsValues(object? sender, IndexingItemEventArgs e)
{
if (e.ValueSet.Category != "content")
{
return;
}
Dictionary<string, List<object>> updatedValues = e.ValueSet.Values.ToDictionary(x => x.Key, x => x.Value.ToList());
if (!updatedValues.ContainsKey("tags"))
{
return;
}
JArray tagsArray = JArray.Parse(updatedValues["tags"].Single().ToString()!);
updatedValues["tagsSplit"] = tagsArray.Select(token => (object)token.Value<string>()!).ToList();
e.SetValues(updatedValues.ToDictionary(x => x.Key, x => (IEnumerable<object>)x.Value));
}
Then I needed to configure the indexer to treat the field values as Raw (which internally uses StringField):
public void Configure(string name, LuceneDirectoryIndexOptions options)
{
if (name.Equals(UmbracoIndexes.ExternalIndexName))
{
options.FieldDefinitions.AddOrUpdate(new FieldDefinition("tagsSplit", FieldDefinitionTypes.Raw));
}
}
Now finally if I query using field:
IBooleanOperation query = _externalIndex.Searcher
.CreateQuery("content", BooleanOperation.And)
.NodeTypeAlias(modelTypeAlias)
.And()
.Field("tagsSplit", tag);
It gives me an exact match.
It is also case-sensitive, but since I'm searching by existing tags and not free-text, that is fine for my use-case.

Google Dart : How does .where() function work?

var fruits = ['apples', 'oranges', 'bananas'];
fruits[0]; // apples
fruits.add('pears');
fruits.length == 4;
fruits.where((f) => f.startsWith('a')).toList();
The example in the documentation shows the above.
I dont really understand the documentation of the method either.
https://api.dartlang.org/stable/1.21.1/dart-collection/IterableMixin/where.html
I currently see a lambda function as a parameter inside where, with where having the argument f. What is f though? Im a bit confused.
It would be great if I could see a working example. As it stands now I dont really get it. I dont know how it works or what it really does apart from that it acts as some sort of filter.
Is an anonymous function and f is the parameter it accepts
(f) => f.startsWith('a')
where(...) calls that passed function for each element in fruits and returns an iterable that only emits the values where the function returned true
where(...) is lazy, therefore the iteration and call of the passed function will only happen when the result is actually accessed, like with .toList().
DartPad example
update
"anonymous" means the function has no name in contrary to a named function like
myFilter(f) => f.startsWith('a');
main() {
fruits.where(myFilter).toList();
}
also
myFilter(f) => f.startsWith('a');
is just a shorter form of
myFilter(f) {
return f.startsWith('a');
}

LINQ to SQL - Filtering the dataset between two nested collections

I have an MVC 3 project in Visual Studio c#. I have a LINQ to SQL query which works fine and by following an example listed elsewhere on stackoverflow:
Comparing two lists using linq to sql
I have been able to successfully reduce my results where my two nested collections match. This is the bit of code that did the trick (example from the link above):
var anyDesiredSkills = canidateSkills.Any( c => desiredSkills.Select( ds => ds.SkillId ).Contains( c.SkillId ) );
I've adapted this successfully, but now I need to be able to filter records using more than one condition. I was wondering if anyone would be able to adapt the above to show how you could include more than one condition?
To give you some background on what my goal is:
A search page where you can select any number of contacts
Each contact added to the search criteria may/may not have a 'role' assigned. If a role is present this should be factored in to the query.
Results returned based on this dynamic criteria.
Thanks in advance for any and all help :O)
It sounds like you're looking for something like:
var desiredSkillIds = desiredSkills.Select(_=>_.SkillId).ToList();
var matchingContacts =
from contact in Contacts
where contact.Role == null || desiredRoles.Contains(contact.Role)
where contact.Skills.Any(cs=> desiredSkillIds.Contains(cs.SkillId))
select contact;
Or in method-based syntax:
var matchingContacts = Contacts
.Where(contact => contact.Role == null || desiredRoles.Contains(contactRole))
.Where(contact => contact.Skills.Any(cs => desiredSkillIds.Contains(cs.SkillId)));
Here's the final code I used:
servicelist = servicelist.Where(
d => d.ContactSelection.Any(
h => model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber)
&&
model.ContactFilter.Select(ds => ds.ContactRole).Contains(h.ContactRole) || model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber) && model.ContactFilter.Select(ds => ds.ContactRole).Contains("0"))
);
Note that the last filter .Contains("0) is the value of '-- select role --' which is an option injected in to the drop down. Hope this helps anyone else!

Problem creating an Entity object/queryable from the result of a LINQ join in MVC

I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);

Entity Framework 4 Linq help - Pulling data from multiple tables filtered

Not sure how this is done, I have my .edmx set up so that the navigation properties match the foreign key relationships on the tables. Not sure if I still need to perform joins or if EF will give me access to the related table data through the navigational properties automatically.
What I need to do it get all the ContentSections and their associated ContentItems based on the ContentView and filtered by the DiversionProgram.CrimeNumber.
I would like to get back IEnumerable, for each ContentSection it should have access to it's ContentItems via the navigation property ContentItems
Thanks
Something like:
using(Entities context = new Entities())
{
IEnumerable<ContentSection> enumerator = context.ContentSections
.Include("ContentItems")
.Where<ContentSection>(cs => cs.ContentView.ContentViewID == someID && cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber))
.AsEnumerable<ContentSection>
}
I've interpreted
based on the ContentView
as cs.ContentView.ContentViewID == someID
This will give you all the ContentSections for a given ContentView. And interpreted
filtered by the DiversionProgram.CrimeNumber
as cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber)
which will give you all those ContentItems that have a specific CrimeNumber.
Or did you mean something else with based on / filtered by. Maybe OrderBy, or all those ContentSections where Any of it's ContentItems would have a certain CrimeNumber?
You can eager load to get all associated records, but when you want to start filtering/ordering, don't bother with Include.
Just do a projection with anonymous types and EF will work out what it needs to do. It's a bit hairy, but it'll work. If it get's too complicated, bite the bullet and use a SPROC.
Now, with that caveat, something like this (off the top of my head):
var query = ctx.ContentView
.Select(x => new
{
ContentSections = x.ContentSections
.Where(y => y.ContentItems
.Any(z => z.DivisionProgram.CrimeNumber = 87))
}).ToList().Select(x => x.ContentSections);
If you use the CTP5 you can do something very unique it looks like this:
var context = new YourEntitiesContext();
var query = context.ContentView.Include(cs => cs.ContentSections
.Select(ci => ci.ContentItems
.Select(dp => dp.DiversionProgram)
.Where(dp.CrimeNumber == crimeNumber)))
.Where(cv => cv.ContentViewID == contentViewID).FirtsOrDefault();
You can learn more about the CTP5 and how it can be used in Database first scenario here
var query = from t1 in studentManagementEntities.StudentRegistrations
join t2 in studentManagementEntities.StudentMarks
on t1.StudentID equals t2.StudentID
select new
{
t1.selected column name,
t2.selected column name
};

Resources