in my Silverlight 4 application, I have an ObservableCollection which consists of objects of a class and is defined by an interface:
interface myInterface()
{
string Name { get; set; }
string Value { get; set; }
}
class myClass() : myInterface
{
...
}
ObservableCollection<myInterface> _collection;
Before adding a new element to the collection, I want to make sure, that the Name-Property does not already exists within the current collection elements.
As I cannot work with contains, I currently iterate through all elements and check each element manually.
private bool CollectionContainsElement(string name2CheckAgainst)
{
foreach (myInterface item in _collection)
if (item.Name.Equals(name2CheckAgainst))
return true;
return false;
}
I have read that this can also be achieved via a Lambda Expression, so I wrote the following:
if (!_collection.Contains(p => p.Name == name2CheckAgainst))
{
...
But now I get an error, saying that the "lambda expression could not be converted to the Type "myInterface", because it is no delegate-type". (Wording may differ, as I translated it from the german version)
I'm not sure what I have to change to make it work. using System.Linq; is included. And the second question (or maybe the primary question): I have read, that the runtime changes from O(1) for the Contains()-method to O(n) - which isn't faster than my current check. So does it even make sense to change it to using the lambda? And finally, is there probably another method in checking for an existing Name-Property in my class?
Thanks in advance,
Frank
You don't have to write a Contains method, the Any method of Linq is already doing that:
if (!_collection.Any(p => p.Name == name2CheckAgainst))
If you want to use a Lambda, you have to change the prototype of your Contains method to accept a Lambda (a lambda is just an alternative way to write an anonymous function):
private bool CollectionContainsElement(Func<myInterface, bool> lambda)
{
foreach (myInterface item in _collection)
if (lambda(item))
return true;
return false;
}
Using a lambda here doesn't change the complexity of your function, it's O(n) in both case. So it's just a matter of preference.
You can use the Linq Any() method. Which is useable like so:
if (!_collection.Any(p => p.Name == name2CheckAgainst))
{
}
The reason why the contains method is O(1) is that under the covers it loads your collection into a HashTable (or similar) and uses the hash code (followed by a call to Equals) to check whether an element is present.
Contains is not a LINQ extension and therefore you can't use lambda expressions with it. It was designed to check if provided object exists in the list.
As others have said, Any is a equivalent lambda-expression compatible extension method
Related
I have an object list and I can add record with that sentence:
List<DragerClass.Alarm> alarms = new List<DragerClass.Alarm>();
public void createAlarm(int i, int[] alarms)
{
alarms.Add(new DragerClass.Alarm(i, DateTime.Now, DragerClass.Dedector.Dedector_Name[i] + " UNDER RANGE"))`;
}
But when I try to remove an item, it behaves like lambda expression doesn't support:
public void removeAlarm(int i)
{
alarms.Remove(x => x.Dedector_No == i);
}
I see that message when I stand on the code
cannot convert lambda expression to type
'Drager_GasDedection.DragerClass.Alarm' because it is not a delegate
type
I'm using Visual Studio 2010 and I also added System.Data.Entity in references. But still same. Thanks for any help.
Take a look at the methods of List<T>. The method Remove(T) simply expects one element. If it is found in the list it is removed, otherwise nothing is done. Remove is not looking for a Predicate<T> that it will check.
RemoveAll(Predicate<T>) however expects a predicate. So you need to call:
alarms.RemoveAll(x => x.Dedector_No == i);
You also have to change = to == in your code since otherwise you are performing an assignment instead of an equality check. Furthermore note that the method will remove all alarms with the given detector number, not just the first.
I have this code (the whole code is not important but can be seen on this link):
internal static class PlayCardActionValidator
{
public static bool CanPlayCard(...)
{
// ...
var hasBigger =
playerCards.Any(
c => c.Suit == otherPlayerCard.Suit
&& c.GetValue() > otherPlayerCard.GetValue());
// ...
}
}
After opening the code in decompiler (ILSpy) for example I noticed the existence of newly created class <>c__DisplayClass0_0 by the C# compiler:
This wouldn't be a problem for me if this code wasn't critical for the performance of the system. This method is called millions of times and the garbage collector is cleaning these <>c__DisplayClass0_0 instances which slows down the performance:
How can I avoid creating this class (his instances and their garbage collecting) when using the Any method?
Why does the C# compiler create this class and is there any alternative of Any() I can use?
To understand the "display class" you have to understand closures. The lambda you pass here is a closure, a special type of method that magically drags in state from the scope of the method it's in and "closes around" it.
...except of course that there's no such thing as magic. All that state has to actually live somewhere real, somewhere that's associated with the closure method and readily available from it. And what do you call the programming pattern where you associate state directly with one or more methods?
That's right: classes. The compiler transforms the lambda into a closure class, then instantiates the class inside the hosting method so the hosting method can access the state in the class.
The only way to not have this happen is to not use closures. If this is really impacting performance, use an old-school FOR loop instead of a LINQ expression.
How can I avoid creating this class (his instances and their garbage collecting) when using the Any method?
Why does the C# compiler creates this class and is there any alternative of Any() I can use?
Other posters already explained the why part, so the better question would be How can I avoid creation of a closure?. And the answer is simple: if lambda is using only the passed parameters and/or constants, the compiler will not create a closure. For instance:
bool AnyClub() { return playerCards.Any(c => c.Suit == CardSuit.Club); }
bool AnyOf(CardSuit suit) { return playerCards.Any(c => c.Suit == suit); }
The first will not create a closure while the second will.
With all that in mind, and assuming you don't want to use for/foreach loops, you can create own extension methods similar to those in System.Linq.Enumerable but with additional parameters. For this particular case, something like this would work:
public static class Extensions
{
public static bool Any<T, TArg>(this IEnumerable<T> source, TArg arg, Func<T, TArg, bool> predicate)
{
foreach (var item in source)
if (predicate(item, arg)) return true;
return false;
}
}
and change the code in question to:
var hasBigger =
playerCards.Any(otherPlayerCard,
(c, opc) => c.Suit == opc.Suit
&& c.GetValue() > opc.GetValue());
Is it possible to complete this method? Is it possible in the latest version of C#? Thinking about this as a DSL to configure a system for watching for certain property changes on certain objects.
List<string> list = GetProps<AccountOwner>(x => new object[] {x.AccountOwnerName, x.AccountOwnerNumber});
// would return "AccountOwnerName" and "AccountOwnerNumber"
public List<string> GetProps<T>(Expression<Func<T, object[]>> exp)
{
// code here
}
In C# 6, you'd use:
List<string> list = new List<string>
{
nameof(AccountOwner.AccountOwnerName),
nameof(AccountOwner.AccountOwnerNumber)
};
Before that, you could certainly break the expression tree apart - the easiest way of working out how is probably to either use an expression tree visualizer, or use the code you've got and put a break point in the method (just make it return null for now) and examine the expression tree in the debugger. I'm sure it won't be very complicated - just a bit more than normal due to the array.
You could possibly simplify it using an anonymous type, if you use:
List<string> list = Properties<AccountOwner>.GetNames(x => new {x.AccountOwnerName, x.AccountOwnerNumber});
Then you could have:
public static class Properties<TSource>
{
public static List<string> GetNames<TResult>(Func<TSource, TResult> ignored)
{
// Use normal reflection to get the properties
}
}
If you don't care about the ordering, you could just use
return typeof(TResult).GetProperties().Select(p => p.Name).ToList();
If you do care about the ordering, you'd need to look at the names the C# compiler gives to the constructor parameters instead - it's a bit ugly. Note that we don't need an expression tree though - we only need the property names from the anonymous type. (An expression tree would work just as well, admittedly.)
Without c# 6 and nameof, you could get a property name from a expression tree like:
using System.Linq.Expressions;
//...
static string GetNameOf<T>(Expression<Func<T>> property)
{
return (property.Body as MemberExpression).Member.Name;
}
Using it like:
GetNameOf(() => myObject.Property);
Not directly usable for an array of objects, but you could make an overload to take an array of expressions... something like:
static string[] GetNameOf(IEnumerable<Expression<Func<object>>> properties)
{
return properties.Select(GetNameOf).ToArray();
}
And use it like
GetNameOf(
new Expression<Func<object>>[]
{
() => x.AccountOwnerName,
() => x.AccountOwnerNumber
}
);
Demonstrating fiddle: https://dotnetfiddle.net/GsV96t
Update
If you go this route, the original GetNameOf for a single property won't work for value types (since they get boxed to object in the Expression and now the expression uses Convert internally). This is easily solvable by changing the code to something like:
static string GetNameOf<T>(Expression<Func<T>> property)
{
var unary = property.Body as UnaryExpression;
if (unary != null)
return (unary.Operand as MemberExpression).Member.Name;
return (property.Body as MemberExpression).Member.Name;
}
Updated fiddle: https://dotnetfiddle.net/ToXRuu
Note: in this updated fiddle I've also updated the overloaded method to return a List instead of an array, since that's what was on your original code
I have a corpus of token-index based documents which offers a query method. The user manually(!) enters a query string which needs to be parsed and evaluated. The corpus should then return a list of all documents matching the given query string. The query language features the simple boolean operators AND, NOT and OR which can also be prioritized by parenthesis.
After some research I already used ANTLR to parse a given query string into a syntax tree.
For example: The query
"Bill OR (John AND Jim) OR (NOT Simon AND Mike)"
is translated in the following syntax tree:
EDIT: Please see the correct graph in Bart Kiers post (copied here):
All nodes in the tree are simple strings and each node knows its parent and children but not its siblings.
As you can see, the ANTLR grammar already dictated the order in which the operations need to be executed: the ones at the bottom of the tree come first.
So what I probably need to do is recusively(?) evaluate all operands in the tree.
In general, I can do a simple search on my corpus using a method Get(string term) for each leaf in the tree (like "Bill" or "John"). Get() returns a list of documents containing the term in the leaf. I can also evaluate the parent of each leaf to recognize a possible NOT operator which would then lead to a result list of documents NOT containing the term in the leaf (using the method Not() instead of Get()).
The AND and OR operator should be transformed into method calls which need two parameters:
AND should call a method Intersect(list1, list2) which returns a list of documents that are in list1 AND in list2.
OR should call a method Union(list1, list2) which returns a list of documents that are either in list1 OR in list2.
The parameters list1 and list2 contain the documents I received before using Get() or Not().
My question is: How can I - semantically and syntactically in C# - evaluate all necessary search terms and use them to call the right operator methods in the correct order? Intuitively it sounds like recursion but somehow I can't picture it - especially since not all methods that need to be called have the same amount of parameters. Or are there maybe entirely other ways to accomplish this?
In Pseudo Code
Set Eval (Tree t) {
switch (t.Operator) {
case OR:
Set result = emptySet;
foreach(child in T.Children) {
result = Union(result, Eval(child));
}
return result;
case AND:
Set result = UniversalSet;
foreach(child in T.Children) {
result = Intersection(result, Eval(child));
}
return result;
case blah: // Whatever.
}
// Unreachable.
}
Does that help?
Or were you looking to optimize the order of evaluations, which probably has books written on it...
I would have expected the following tree to be generated:
(note that in your AST, the OR node has 3 children)
Either way, if you have created an ANTLR grammar that is able to create an AST (whether in the form of your original image, or mine posted above), it means that you have defined the proper operator precedence in your grammar. In that case, you shouldn't be confused to execute the order of your operators since your tree already mandates that (John <- AND -> Jim) and (NOT -> Simon) are to be evaluated first.
Could you perhaps post the ANTLR grammar you've been working on?
Also, you're talking about sets, but in your example, only single values are shown, so I get the impression your language is a bit more complex than you've shown so far. Perhaps you could explain your actual language, instead of a dumbed-down version of it?
PS. The source that created the image can be found here: http://graph.gafol.net/elDKbwzbA (ANTLR grammar also incuded)
I'm not familiar with the object model which ANTLR generates but assuming its something like this:
class BinaryNode : Node
{
public Node LeftChild;
public Node RightChild;
public readonly string Operator;
}
class UnaryNode : Node
{
public Node Child;
public readonly string Operator;
}
class TerminalNode : Node
{
public readonly string LeafItem;
}
class Node { }
public class Executor
{
public IEnumerable<object> Get(string value)
{
return null;
}
public IEnumerable<object> GetAll()
{
return null;
}
public IEnumerable<object> GetItems(Node node)
{
if (node is TerminalNode)
{
var x = node as TerminalNode;
return Get(x.LeafItem);
}
else if (node is BinaryNode)
{
var x = node as BinaryNode;
if (x.Operator == "AND")
{
return GetItems(x.LeftChild).Intersect(GetItems(x.RightChild));
}
else if (x.Operator == "OR")
{
return GetItems(x.LeftChild).Concat(GetItems(x.RightChild));
}
}
else if (node is UnaryNode)
{
var x = node as UnaryNode;
if (x.Operator == "NOT")
{
return GetAll().Except(GetItems(x.Child));
}
}
throw new NotSupportedException();
}
}
Note however this evaluates the query eagerly, which is not optimal. But it should give you an idea of how recursion would work.
I'm not exactly sure what you're trying to do, but I think I would turn the AST into a Func<Person, bool>. Each leaf node can be evaulated to a Func<Person, bool> for example p => p.Name == "Bill" AND, OR, and NOT can be implemented as higher order functions for example:
public static Func<T, bool> And<T>(Func<T, bool> a, Func<T, bool> b)
{
return t => a(t) && b(T);
}
Once you've done all this and collapsed your AST into a single Func<Person, bool>, you can pass that as the parameter to the Where() extension method on any type that implements IEnumerable<Person>.
In other words, I would first "compile" the AST into a Func<Person, boo>, and then use LINQ to Objects to actually filter my collection. Compiling should be easy because your AST is an implementation of the Composite design pattern. Each node should be able to expose the method Func<Person, bool> Compile().
I have next LINQ query to read App.config to instantiate objects using fully qualified types stated inside:
var strategies = from strategy in section.Strategies
let indicators = (
from indicator in strategy.Indicators
select (IIndicatorReader)Activator.CreateInstance(Type.GetType(indicator.Type), bot.Mt, section.Symbol))
let orders = (
from order in strategy.Orders
select new OrderInfo(order.Id, order.Operation.Value, order.Amount))
select (IStrategy)Activator.CreateInstance(Type.GetType(strategy.Type), section.Symbol, strategy.Amount, strategy.Limit, indicators, orders);
So each time inside the strategy I call
indicatorList.Select(i => i.Operation)
this instantiation occurs:
(IIndicatorReader)Activator.CreateInstance(Type.GetType(indicator.Type), bot.Mt, section.Symbol))
and appropriate class's constructor is called.
But an indicator stated in App.config first is instantiated twice, all other - once. How can it be?? I will be happy to provide any additional information required.
My indicator collection:
public class IndicatorElementCollection : ConfigurationElementCollection, IEnumerable<IndicatorElement>
{
...
public new IEnumerator<IndicatorElement> GetEnumerator()
{
return this.OfType<IndicatorElement>().GetEnumerator();
}
}
Implementation of GetEnumerator() conversion from non-generic to generic is taken from this question on SO.
Another implementation:
foreach (OrderElement element in (System.Collections.IEnumerable)this)
{
yield return element;
}
works in the same manner.
The LINQ expression indicators will be re-evaluated every time you call GetEnumerator. You need to force a single evaluation by invoking ToList or ToArray. This could of course result in memory space issues if you are expecting many indicators.