This is my main.dart:
import 'edgecases.dart';
main () {
var card = edgecases(0)['input']['cards'];
var query = edgecases(0)['input']['query'];
var result = locate_card(edgecases(0)['input']['cards'], edgecases(0)['input']['query']);
var output = edgecases(0)['output'];
print("Cards:- $card");
print("Query:- $query");
print("Output:- $result");
print("Actual answer:- $output");
}
And this is my edgecases.dart:
edgecases ([edgecasenumber = null]) { //You may make it required, I provided a null as default to check if my syntax is going right.
List tests = [];
var edge1 = {'input': {
'cards': [13, 11, 10, 7, 4, 3, 1, 0],
'query': 1
}, 'output': 6};
tests.addAll([edge1]);
if (edgecasenumber == null){ // This if is useless here so you may
return 'Null type object coud not be found.';
} else {
return tests.elementAt(edgecasenumber); // Indexing in dart also starts with 0.
}
}
locate_card (List cards, int query){
int lo = 0;
int hi = cards.length - 1;
print('$lo $hi');
while (lo <= hi) {
//print('hello'); Uncomment to see if it is entering the loop
var mid = (lo + hi) ~/ 2;
var mid_number = cards[mid];
print("lo:$lo ,hi:$hi, mid:$mid, mid_number:$mid_number");
if (mid_number == query){
return mid;
} else if (mid_number < query) {
hi = mid - 1;
} else if (mid_number > query) {
lo = mid + 1;
};
return -1; //taking about this line
};
}
[I have cut short the code here so you may find some things as unnecessary so just ignore it XD]
Actually I am trying to implement binary search here(I have previously successfully implemented it in python, I am implementing in dart to learn the language.)
On testing it with first edge case(that is on running the command dart main.dart), I found that it is returning the value -1 which was wrong, so I tried commenting the return -1; line in edgecases.dart file to see what happens as it was made to handle another edge case(edgecase if the list is empty, here I have removed that for simplicity). I am not able to understand why it is returning -1 if it gives the right value on commenting that line. Any possible explainations and solutions?
Thanks in advance!
You almost did it right. Just place the return -1; after the while loop's closing brace at the very end of locate_card.
In Python, you can specify a "step" argument to a list slice that specifies the separation between indices that are selected to be in the slice:
my_list[start:stop:step]
However, none of the list methods in Dart seem to offer this functionality: sublist and getRange just take the start and end index.
How can I do this in Dart without using an ugly for-loop?
For example, to select only the even indices of a list I currently see no alternative to this:
List<Object> myList = ...;
List<Object> slice = [];
for (var i = 0; i < myList.length; i += 2) {
slice.add(myList[i]);
}
Or slightly less ugly with a list comprehension:
[for (var i = 0; i < myList.length; i += 2) myList[i]]
I could write my own function or extension method, but that defeats the purpose, I'm looking for ideally a built-in or a third package solution.
For this you can create extension on list to return custom result.
List<T> slice([int? start, int? end, int? step]) {
if (start == null && end == null && step == null) {
return this!;
} else if (start != null && end == null && step == null) {
return this!.sublist(start);
} else if (start != null && end != null && step == null) {
return this!.sublist(start, end);
} else if (start != null && end != null && step != null) {
// iterate over the list and return the list
// iterator start from start index
// iterator end at end index
// iterator step by step
final list = <T>[];
for (var i = start; i < end; i += step) {
list.add(this![i]);
}
return list;
} else {
return this!;
}
}
You can use the slice extension on any list. Below are examples of how to use it.
Example 1
This example will return the slice list of the list depending starting and ending index.
final list1 = [1, 2, 3, 4, 5];
final result = list1.slice(1, 4);
print(result); // [2, 3, 4]
Example 2
This example will return the slice list of the list depending starting index.
final list1 = [1, 2, 3, 4, 5];
final result = list1.slice(1);
print(result); // [2, 3, 4, 5]
Complate program.
You can run this example in Dartpad to check results.
void main() {
final list1 = [1, 2, 3, 4, 5,6,7,8,9,10,11,12,13,14,15,15,17,18,19,20];
// Example - 1
final result = list1.slice(1, 4);
print(result); // [2, 3, 4]
//Example - 2
final result2 = list1.slice(10);
print(result2); // [11, 12, 13, 14, 15, 15, 17, 18, 19, 20]
//Example - 3
final result4 = list1.slice(4, 10, 2);
print(result4); // [5, 7, 9]
//Example - 4
final result3 = list1.slice();
print(result3); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 17, 18, 19, 20]
}
extension ListHelper<T> on List<T>? {
List<T> slice([int? start, int? end, int? step]) {
if (start == null && end == null && step == null) {
return this!;
} else if (start != null && end == null && step == null) {
return this!.sublist(start);
} else if (start != null && end != null && step == null) {
return this!.sublist(start, end);
} else if (start != null && end != null && step != null) {
// iterate over the list and return the list
// iterator start from start index
// iterator end at end index
// iterator step by step
final list = <T>[];
for (var i = start; i < end; i += step) {
list.add(this![i]);
}
return list;
} else {
return this!;
}
}
}
You can easily create your own slice method in Dart.
The first thing to decide is whether you want it to be lazy or eager—does it create a list or an iterable.
The traditional Dart way would be an iterable, created from another iterable, which is also slightly more complicated to write.
extension LazySlice<T> on Iterable<T> {
/// A sub-sequence ("slice") of the elements of this iterable.
///
/// The elements of this iterable starting at the [start]th
/// element, and ending before the [end]th element, or sooner
/// if this iterable has fewer than [end] elements.
/// If [end] is omitted, the sequence continues
/// to the end of this iterable.
/// If [step] is provided, only each [step]th element of the
/// [start]..[end] range is included, starting with the first,
/// and skipping `step - 1` elements after each that is included.
Iterable<T> slice([int start = 0, int? end, int step = 1]) {
// Check inputs.
RangeError.checkNotNegative(start, "start");
if (end != null && end < start) {
throw RangeError.range(end, start, null, "end");
}
if (step < 1) {
throw RangeError.range(step, 1, null, "step");
}
// Then return an iterable.
var iterable = this;
if (end != null) iterable = iterable.take(end);
if (start > 0) iterable = iterable.skip(start);
if (step != 1) iterable = iterable.step(step);
return iterable;
} // slice
/// Every [step] element.
///
/// The first element of this iterable, and then every
/// [step]th element after that (skipping `step - 1`
/// elements of this iterable between each element of
/// the returned iterable).
Iterable<T> step(int step) {
if (step == 1) return this;
if (step < 1) {
throw RangeError.range(step, 1, null, "step");
}
return _step(step);
}
/// [step] without parameter checking.
Iterable<T> _step(int step) sync* {
var it = iterator;
if (!it.moveNext()) return;
while (true) {
yield it.current;
for (var i = 0; i < step; i++) {
if (!it.moveNext()) return;
}
}
} // _step
} // extension LazySLice
Working with a list is much easier:
extension EagerSlice<T> on List<T> {
List<T> slice([int start = 0, int? end, int step = 1]) {
if (step == 1) return sublist(start, end); // Checks parameters.
end = RangeError.checkValidRange(start, end, length);
if (step < 1) {
throw RangeError.range(step, 1, null, "step");
}
return <T>[for (var i = start; i < end; i += step) this[i]];
}
}
(Effectively the same approach proposed by #Anakhand in the comments above, just with better parameter checking.)
The list approach is easier, mainly because we don't already have a step method on iterables, which picks every nth element.
I am using fold on an array which hasn't been assign to a variable and want to check whether the element is the last value. With a conventional for loop I can do this:
List<int> ints = [1, 2, 3];
int sum = 0;
for (int num in ints]) {
if (num != ints.last) {
sum = sum + num;
}
}
print(sum);
Is it possible to do this with fold instead?
int foldSum = [1, 2, 3].fold(0, (int prev, element) => prev + element);
print(foldSum);
I can't find any way of check when fold is at the last value. Note: this is a simplified example of my problem and the reason the list isn't assigned to a variable (allowing me to use .last) is because it is the result of a call to .map().
For completeness, below is the actual code (which won't obviously won't be runnable in isolation but will help illustrate my problem) I am trying to convert to use .map and .fold:
String get fieldsToSqlInsert {
String val = "";
for (Column column in columns) {
if (data.containsKey(column.name)) {
val = '$val "${data[column.name]}"';
} else {
val = "$val NULL";
}
if (column != columns.last) {
val = "$val,";
}
}
return val;
}
But it doesn't work because I don't know how to check when fold is at the final element:
String get fieldsToSqlInsert => columns
.map((column) =>
data.containsKey(column.name) ? data[column.name] : "NULL")
.fold("", (val, column) => column != columns.last ? "$val," : val);
If you simply want to exclude the last element from further calculation, you can just use take to do so:
String get fieldsToSqlInsert => columns.take(columns.length - 1)...
I need to get all possible subsets of an array.
Say I have this:
<int>[1, 2, 3]
How do I get this?
[], [1], [2], [3],[1, 2], [2, 3], [1, 3], [1, 2, 3]
I am interested in all subsets. For subsets of specific length, refer to the following questions:
How to find all subsets of a set in JavaScript?
Here is my take on it, with only native function as in your link:
List getAllSubsets(List l) => l.fold<List>([[]], (subLists, element) {
return subLists
.map((subList) => [
subList,
subList + [element]
])
.expand((element) => element)
.toList();
});
If you want a specific size:
List getSizedSubsets(List l, int size) =>
getAllSubsets(l).where((element) => element.length == size).toList();
I'd probably go with something simple like:
Iterable<Set<E>> subsets<E>(Set<E> elements) sync* {
if (elements.length >= 32) {
// Otherwise there'll be more than 2^32 subsets. And bitops will overflow in JS.
throw ArgumentError.value(elements, "elements", "must have less than 32 elements");
}
var list = [...elements];
var subsetCount = 1 << list.length;
for (var i = 0; i < subsetCount; i++) {
yield {
for (var j = 0, bit = 1; j < elements.length; j++, bit <<= 1)
if (i & bit != 0) list[j]
};
}
}
Another approach is to only have one set, and then update it iteratively to contain different elements. It's possible to go through all the sets doing only single-element changes on each step (using Gray-code):
/// Iterates a set through all combinations of its elements.
///
/// Adds and removes elements from [set] to make it iterate through all
/// possible combinations of its initial elements.
/// The current value of the iterator is always [set].
/// If iterated through to the end, the [set] ends up with all its original elements.
Iterable<Set<E>> subsets<E>(Set<E> set) sync* {
if (set.length >= 32) {
throw ArgumentError.value(set, "set", "must have less than 32 elements");
}
var list = [...set];
var prev = 0;
var counter = 0;
do {
yield set;
var next = ++counter ^ (counter >> 1);
var bit = prev ^ next; // One bit set.
var index = bit.bitLength - 1;
if (index >= list.length) index = 0;
var element = list[index];
if (next & bit == 0) {
set.add(element);
} else {
set.remove(element);
}
prev = next;
} while (set.length < list.length);
}
Is there a better idiom for auto-initializing Map values to 0 than the following? In the following code there is an asymmetry between the approach to adding a value to a target of type List versus int.
main() {
addToList(Map m, v) =>
m..putIfAbsent('foo', () => []).add(v);
///////////////////////////////////////////////////////////
// Not allowed (expression is not assignable)
// addToScalar(Map m, v) =>
// m..putIfAbsent('foo', () => 0) += 3;
addToScalar1(Map m, v) {
m.putIfAbsent('foo', () => 0);
m['foo'] += v;
return m;
}
addToScalar2(Map m, v) {
if(m.containsKey('foo')) {
m['foo'] += v;
} else {
m['foo'] = v;
}
return m;
}
print(addToList({}, 3));
print(addToScalar1({}, 3));
print(addToScalar2({}, 3));
}
Conceptually addToList and addToScalar do similar things. But the analog for the int stored as a value type might be:
m.putIfAbsent('foo', () => 0) += someValue
which will not work since what is returned from putIfAbsent is not assignable. So with both the working approaches used in the scalar case the lookup in the map for key 'foo' is being done twice. Can this be avoided with the Map API?
No, you cannot currently avoid two lookups in order to modify a map value.
We have considered, but never decided on, a way to achieve that (e.g., an "update" method).
The Two shortest/most efficient solution to your problem are:
int _returnZero() => 0; // Toplevel or static function.
...
map[key] = map.putIfAbsent(key, _returnZero) + v;
...
and:
int value = map[key];
map[key] = (value == null) ? v : value + v;