How cascading modifies original object? - dart

var intList = [3, 2, 1];
var sorted = intList..toList()..sort(); // [1, 2, 3]
var sorted2 = intList..toList().sort(); // [3, 2, 1]
Why my original list is also being modified in first sort and which list is being sorted in second sort?
NOTE: I'm not looking for the correct way to do it which is this:
var sorted = intList.toList()..sort(); // [1, 2, 3]

x..y evalutes to x. Cascade chains are evaluated left-to-right, so x..y..z is the same as (x..y)..z. Your first example therefore makes calls to toList() and to sort() on the original object.
Member access (.) has higher precedence than the cascade operator (..). Your second example calls sort() on the copy returned by toList(), not on the original object.

Related

Is it possible to remove duplicates in Dart with another variable

I have searched a lot for removing duplicates from a list in Dart using ANOTHER variable.
Here is what I mean:
List<int> numbers = [1, 2, 3, 4];
// This list has 4 new elements than the first one
List<int> moreNumbers = [1, 2, 3, 4, 5, 6, 7, 8];
// Now I want to push the moreNumbers unique elements to the numbers one
I want to push it so the end result for the numbers variable should be:
[1, 2, 3, 4, 5, 6, 7, 8];
Is it possible?
void main() {
var lst = [1,2,3,4];
var lst2 = [1,2,3,4,5,6,7,8];
var s = {...(lst+lst2)};
print(s.toList());
}
The trivial approach would be:
for (var number in moreNumbers) {
if (!numbers.contains(number)) {
numbers.add(number);
}
}
Not particularly efficient if numbers is long, because contains on a list can take time proportional to the length of the list.
The time/space trade-off would be creating a set from numbers, because sets have cheap contains:
var alsoNumbers = numbers.toSet(); // Also linear, but only happens once.
for (var number in moreNumbers) {
if (alsoNumbers.add(number)) { // true if elements was added
numbers.add(number);
}
}
(Using add instead of contains ensures that you update the set with new values, so you won't add the same new value twice.)
If you could just make numbers a Set to begin with, it would be much easier to avoid duplicates, just do numbers.addAll(moreNumbers).

What is difference between filtering: Where and takeWhile in Dart

I see both of them (where and takeWhile) has the same function .. or I might miss something here!
The documentation for Iterable.where says:
Returns a new lazy Iterable with all elements that satisfy the predicate test.
The documentation Iterable.takeWhile says:
Returns a lazy iterable of the leading elements satisfying test.
(emphasis added).
In other words, Iterable.takeWhile will stop iterating once it reaches the first item that does not satisfy the test callback.
A concrete example:
var list = [1, 1, 2, 3, 5, 8];
print(list.where((x) => x.isOdd).toList()); // Prints: [1, 1, 3, 5]
print(list.takeWhile((x) => x.isOdd).toList()); // Prints: [1, 1]

add an element to 2d list using dart with add() method

the normal list in dart 1d can use with it many methods like insert remove indexOf etc . but in 2d list many of list methods can't work with it ? why an example below
var lista = [1,2,3,4,5] ;
lista.add(6);
print(lista);
Works fine
var listb = [[1,2,3],
[4,5]
];
listb.add(6); // wont add cause the argument type 'int' can't be assigned to the parameter type 'List'.
accept it only when listb.add([6]); but add this as new element in list i want to add in [4,5] a number only ?!
If you want to add to the second list of the lists, just do so:
void main() {
var listb = [[1,2,3], [4,5]];
listb[1].add(6);
print(listb);
}
This prints
[[1, 2, 3], [4, 5, 6]]
You wanted the first list to know that you want to add to the second of it's elements. That is not how programming works, the compiler does not guess what you may want. You have to explicitly tell it what to do.

How can I order objects by price in Dart?

I have tried to sort the list of objects based on the price of each individual object has. However, I have got this error the expression here has a type of void, and therefore it cannot be used
class Item{
String productName;
double price;
}
List<Item> items = ...;
items.sort((a, b) => a.price.compareTo(b.price));
List.sort modifies the object on which it is call. It doesn't return any value and you have to use the original list.
var list = [3, 1, 2];
list.sort();
print(list); // displays [1, 2, 3]
If you want to inline the .sort() to use the list directly, you can use the cascade notation:
var list = [3, 1, 2]..sort();
print(list); // displays [1, 2, 3]
// or
var list = [3, 1, 2];
print(list..sort()); // displays [1, 2, 3]

In Rails, how do I figure out if an array of objects contains specific attributes matching given values?

I'm using Ruby on Rails 5.0.1 with Ruby 2.4. I have an array of objects, stored in the array, "results." Each object has a numeric attribute
numeric_attr
I would like to know, given my array, how I can tell if I have exactly one object with a numeric attribute value of "1" and incrementing by one. Order is not important. So, for instance, if I have an array of three objects,
[MyObject(numeric_attr = 2), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)]
I want to know if I have exactly one object with numeric_attr = 1, another object with numeric_attr = 2, and another with numeric_attr = 3. So the above satisfies the condition. The below example does not
[MyObject(numeric_attr = 4), MyObject(numeric_attr = 1), MyObject(numeric_attr = 3)]
because although there is an object with numeric_attr = 1, there is no object with numeric_attr = 2. It is possible thet the numeric_attr field is nil. How can I figure this out?
This one-liner should work:
results.map(&:numeric_attr).sort == (1..results.count).to_a
Explanation:
results
#=> [#<MyObject:... #attr=2>, #<MyObject:... #attr=3>, #<MyObject:... #attr=1>]
results.map(&:attr)
#=> [2, 3, 1]
results.map(&:attr).sort
#=> [1, 2, 3]
(1..results.length).to_a
#=> [1, 2, 3]
# therefore:
results.map(&:attr).sort == (1..results.count).to_a
#=> true
If there is a chance that numeric_attr is nil:
results.map(&:attr).compact.sort == (1..results.count).to_a
Of course, if there is even a single nil value, the result is guaranteed to be false.
If the sequence could start at any number, not just 1:
results.map(&:attr).sort == results.count.times.to_a.
map { |i| i + results.map(&:attr).sort.first }
This is not very efficient though, as it sorts the numbers twice.
If they always start at 1 #Máté's solution works, if they can start at any arbitrary number then you could:
count = 0
array_objects.sort_by(&:numeric_attr).each_cons(2) {|a,b| count+=1 if a.numeric_attr==b.numeric_attr-1 }
count+1==array_objects.count
Not as elegant but handles a lot more situations

Resources