adding objects to list if it doesn't contain it - dart

I'm trying to add object to a list only if it wasn't added already .. like this:
for (var interest in poll.poll.interests) {
InterestDrop n = new InterestDrop(interest, false);
print(interest);
print(dropInterestsList);
print(dropInterestsList.contains(n));
if (!(dropInterestsList.contains(n))){
dropInterestsList.add(n);
}
}
but this always return false and add the object even when its already there ... how to solve this?
ANSWER:
class InterestDrop {
String name;
bool isClicked;
InterestDrop(this.name, this.isClicked);
bool operator == (o) => o is InterestDrop && name == o.name && isClicked == o.isClicked;
int get hashCode => hash2(name.hashCode, isClicked.hashCode);
}

You need to override the equality operator in your custom class.
From the docs:
The default behavior for all Objects is to return true if and only if
this and other are the same object.
So your contains method will only return true if your array contains the exact object you are comparing against.

You need to do something like this:
class InterestDrop {
operator ==(InterestDrop other) => identifier == other.identifier;
}

Related

Searching a List of objects for a particular object in dart using "where"

I would like to obtain an object from a List based on a specific search criteria of its member variable
this is the code I am using
class foo
{
foo(this._a);
int _a;
}
List<foo> lst = new List<foo>();
main()
{
foo f = new foo(12);
lst.add(f);
List<foo> result = lst.where( (foo m) {
return m._a == 12;
});
print(result[0]._a);
}
I am getting the error and not sure how to resolve this
Uncaught exception:
TypeError: Instance of 'WhereIterable<foo>': type 'WhereIterable<foo>' is not a subtype of type 'List<foo>'
I am trying to search for an object whose member variable a == 12. Any suggestions on what I might be doing wrong ?
The Iterable.where method returns an iterable of all the members which satisfy your test, not just one, and it's a lazily computed iterable, not a list. You can use lst.where(test).toList() to create a list, but that's overkill if you only need the first element.
You can use lst.firstWhere(test) instead to only return the first element, or you can use lst.where(test).first to do effectively the same thing.
In either case, the code will throw if there is no element matched by the test.
To avoid throwing, you can use var result = lst.firstWhere(test, orElse: () => null) so you get null if there is no such element.
Another alternative is
foo result;
int index = lst.indexWhere(test);
if (index >= 0) result = lst[index];
The answer is simple. Iterable.where returns an Iterable, not a List. AFAIK this is because _WhereIterable does its computations lazily.
If you really need to return a List, call lst.where(...).toList().
Otherwise, you can set result to be an Iterable<foo>, instead of a List<foo>.
or you can go crazy and do this:
bool checkIfProductNotFound(Map<String, Object> trendingProduct) {
bool isNotFound = this
._MyProductList
.where((element) => element["id"] == trendingProduct["id"])
.toList()
.isEmpty;
return isNotFound ;
}

Dart Cannot find a value in the map even through the keys are equal

I have a map that has a complex object as a key
Map<TimeseriesNode , MyObject> myMap = {};
TimeseriesNode class has implemented hashCode and == operator
class TimeseriesNode {
String product;
String model;
String element;
String locationName;
String locationSuffix;
TimeseriesNode.create(this.product, this.model, this.element, this.locationName, this.locationSuffix);
int get hashCode {
return hashObjects([product, model, element, locationName, locationSuffix]);
}
bool operator ==(other) {
if (other is! TimeseriesNode) return false;
TimeseriesNode key = other;
return (key.element == element
&& key.locationName == locationName
&& key.locationSuffix == locationSuffix
&& key.model == model
&& key.product == product);
}
}
(method hashObjects comes from import "package:quiver/core.dart";)
One part of my application creates the keys and adds them to the map.
Another part of the application creates a new TimeseriesNode (which is equal to the original key) and then uses this instance to query the map.
MyObject obj = myMap[ node];
Oddly the map returns null. I have done some debugging and found that myMap[node] calls the following code in the dart:collection-patch_compact_hash code
V operator [](Object key) {
var v = _getValueOrData(key);
return identical(_data, v) ? null : v;
}
When I inspect v, I can see 'v' is the object that was originally added to the map, but the code returns null.
If I put a break point on my equals method, it is never called.
What is going on?
The fields you use to calculate the hashcode should be immutable (final). I guess you change one of these fields after you inserted the element into the map. This results in the map not finding the instance by hashcode and therefore doesn't reach the state where it does the equals check.

Grails: Comparing two unsaved domain class objects always returns false

I need to compare several domain class objects while they are still unsaved, however, I always keep getting a false result from the comparison. Turns out even the following comparison will return false:
new DomainClass().equals(new DomainClass())
Since both are brand new objects they should both have identical data and should be equal to each other. Unfortunately the equals method (or the == operator) returns false. Is there another correct way of performing this comparison?
Your code same with this:
a = new DomainClass();
b = new DomainClass();
a.equals(b)
So clearly the test must return false as far as a and b are not referencing same object.
If you want value based comparing:
Iterate over the fields and compare them one by one
Or check here for a more formal way of doing it.
you can use 'spaceship operator' (<=>) which work like compareTo()
or you can override equals() method in your DomainClass that make able to use this code
new DomainClass().equals(new DomainClass())
to override equals() you can use #EqualsAndHashCode annotation
this annotation automatically generate equals() and hashcode() methods
So, you class will look like this:
#EqualsAndHashCode
class DomainClass(){
String field1
String filed2
etc
}
and your generated equals method will look like this:
public boolean equals(java.lang.Object other)
if (other == null) return false
if (this.is(other)) return true
if (!(other instanceof DomainClass)) return false
if (!other.canEqual(this)) return false
if (field1 != other.field1) return false
if (field2 != other.field2) return false
// etc
return true
}
For more details look at this http://groovy.codehaus.org/api/groovy/transform/EqualsAndHashCode.html

How to cache aggregate column values on Doctrine_Record instance?

Lets say i have a record class that often gets queried with dyanmic colums that are MySQL aggregate values:
$results = Doctrine_Core::getTable('MyRecord')->creatQuery('m')
->select('m.*, AVG(m.rating) as avg_rating, SUM(m.id) as nb_related')
->innerJoin('m.AnotherRecords a')
->where('m.id = ?')
->fetchOne();
Now lets say i want a method on that record to check if the aggregate columns exist from when the record was queried, and if not then i want to go ahead an issue a separate query to get these values:
// this doesnt actually work because of filterSet and filterGet
// but its general idea
public function getAverageRating($wtihNbRelated = false)
{
if(!isset($this->avg_rating) || ($withNbRelated && !isset($this->nb_related))
{
$rating = $this->getTable()->getAverageRating($this, $withNbRelated);
$this->avg_rating = $rating['avg_rating'];
if($withNbRealted)
{
$this->nb_related = $rating['nb_related'];
}
}
return $withNbRelated
? array('avg_rating' => $this->avg_rating, 'nb_related' => $this->nb_related)
: array('avg_rating' => $this->avg_rating);
}
Is there an easy way (ie. not writing a custom hydrator) to do this?
Simple answer really. I forgot that Doctrine prefixes all its direct protected members with _. So, even though i initially tried manipulating the data member i was forgot the prefix giving me the same result as if i tried $this->avg_rating or its accessor method. The solution was:
public function getAverageRating($wtihNbRelated = false)
{
if(!isset($this->_data['avg_rating']) || ($withNbRelated && !isset($this->_data['nb_related']))
{
$rating = $this->getTable()->getAverageRating($this, $withNbRelated);
$this->_data['avg_rating'] = $rating['avg_rating'];
if($withNbRealted)
{
$this->_data['nb_related'] = $rating['nb_related'];
}
}
return $withNbRelated
? array('avg_rating' => $this->_data['avg_rating'], 'nb_related' => $this->_data['nb_related'])
: array('avg_rating' => $this->_data['avg_rating']);
}

ASP.Net MVC : Get query values with no key

I have URL: http://site.com/page.aspx?update
how do I check if that update value is present?
HttpValueCollection treats that as an entity with null key. I have tried:
var noKeyValues = Request.QueryString.GetValues(null);
if (noKeyValues != null && noKeyValues.Any(v=>v==update)) ...
but it gives me a frowny line, because GetValues' argument is decorated with [NotNull].
so I end up doing:
var queryValuesWithNoKey =
Request.QueryString.AllKeys.Select((key, index) => new { key, value = Request.QueryString.GetValues(index) }).Where(
item => item.key == null).Select(item => item.value).SingleOrDefault();
if (queryValuesWithNoKey != null && queryValuesWithNoKey.Any(v => v.ToLower() == "update")) live = true;
not the most elegant workaround. Is there a better way to get key-less value from query string?
You can use
Request.QueryString[null]
to retrieve a comma separated list of keys with no values. For instance, if your url is:
http://mysite/?first&second
then the above will return
first,second
In your case, you could just do something like:
if(Request.QueryString[null] == "update")
{
// it's an update
}
if that's the only key you would use
Request.QueryString.ToString() to get the "update" value
I know I'm late to the party, but this a function that I use for this kind of task.
internal static bool HasQueryStringKey(HttpRequestBase request, string key)
{
// If there isn't a value, ASP will not recognize variable / key names.
string[] qsParts = request.QueryString.ToString().Split('&');
int qsLen = qsParts.Length;
for (int i = 0; i < qsLen; i++)
{
string[] bits = qsParts[i].Split('=');
if (bits[0].Equals(key, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
You may need to update it so that it is case sensitive, or uses different arguments depending on your purposes, but this has always worked well for me.

Resources