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);
}
Related
Is there a method we use to reach the desired number in an array given in dart language.. I can do this for binary ones, but I can't do it for a code that finds the sum of 3 or more elements
For example
Input: candidates = [10,1,2,7,6,1,5], target = 8
Output:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
this is the my code i have done until now
void main() {
var candidates = [10, 1, 2, 7, 6, 1, 5], target = 8;
var answer = [];
for (int i = 0; i < candidates.length; i++) {
for (int j = 0; j < candidates.length; j++) {
if (candidates[i] + candidates[j] == target && i != j && i < j) {
answer.add([candidates[i], candidates[j]]);
}
}
}
}
I am sure this can be done more efficient but since the solution is for some Leetcode assignment, I don't really want to spend too much time on optimizations.
I have tried added some comments in the code which explains my way of doing it:
void main() {
getSumLists([10, 1, 2, 7, 6, 1, 5], 8).forEach(print);
// [5, 1, 2]
// [1, 6, 1]
// [1, 7]
// [6, 2]
getSumLists([2, 5, 2, 1, 2], 5).forEach(print);
// [2, 1, 2]
// [5]
}
Iterable<List<int>> getSumLists(
List<int> candidates,
int target, {
List<int>? tempAnswer,
int sum = 0,
}) sync* {
// We cannot use default value in parameter since that makes list const
final tempAnswerNullChecked = tempAnswer ?? [];
if (sum == target) {
// We got a result we can return.
// OPTIMIZATION: If you know the returned list from each found result is not
// being used between found results, you can remove the `.toList()` part.
yield tempAnswerNullChecked.toList();
} else if (sum > target) {
// No need to search further in this branch since we are over the target
return;
}
// Make a copy so we don't destroy the input list but also so it works even
// if provided list as input is non-growing / non-modifiable
final newCandidates = candidates.toList();
while (newCandidates.isNotEmpty) {
// We take numbers from the end of the list since that is more efficient.
final number = newCandidates.removeLast();
// Recursive call where we return all results we are going to find given
// the new parameters
yield* getSumLists(
newCandidates,
target,
tempAnswer: tempAnswerNullChecked..add(number),
sum: sum + number,
);
// Instead of creating a new tempAnswerNullChecked, we just reuse it and
// make sure we remove any value we are temporary adding
tempAnswerNullChecked.removeLast();
// Ensure we don't get duplicate combinations. So if we have checked the
// number `1` we remove all `1` so we don't try the second `1`.
newCandidates.removeWhere((element) => element == number);
}
}
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 have List list= [1,2,3,4,4,4,9,6,7,7,7,8,8,8,8,8,8,8];
how can i return 8 as max repeated value
Something like this?
void main() {
final list = [1, 2, 3, 4, 4, 4, 9, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8];
print(findMaxDuplicatedElementInList(list)); // 8
}
T findMaxDuplicatedElementInList<T>(Iterable<T> list) => list
.fold<Map<T, int>>(
{},
(map, element) =>
map..update(element, (value) => value + 1, ifAbsent: () => 1))
.entries
.reduce((e1, e2) => e1.value > e2.value ? e1 : e2)
.key;
I'd just write it out, as straight-forward as possible:
Assuming the equal elements are always adjacent, and list cannot be empty, return arbitrary element with maximal count if there is more than one:
T maxDuplicated<T>(List<T> elements) {
var element = elements.count;
var count = 1;
var maxElement = element;
var maxCount = count;
for (var i = 1; i < elements.length; i++) {
var nextElement = elements[i];
if (element != nextElement) {
element = nextElement;
count = 1;
} else {
count += 1;
if (count > maxCount) {
maxElement = element;
maxCount = count;
}
}
}
return maxElement;
}
Assuming elements come in random order, so we need to remember every element we have seen,
still not allowing an empty list as input:
T maxDuplicated<T>(List<T> elements) {
var maxCount = 1;
var maxElement = elements.first
var seen = <T, int>{maxElement: maxCount};
for (var i = 1; i < elements.length; i++) {
var element = elements[i];
var count = seen[element] = (seen[element] ?? 0) + 1;
if (count > maxCount) {
maxCount = count;
maxElement = element;
}
}
return maxElement;
}
(Alternatively, I'd sort the list first, if allowed, to always be in the former situation. It's not faster than using a map, if we assume hash map lookup to be a constant time operation, but it will be more memory efficient.)
How can I find the closest value in a list, which will return me the higher value?
Example: List of [3,7,12,19] if my value is 8 how can I get the nearest(larger) value 12? i want this logic in dart.
Just filter the List only for the values higher or equal to your number and get the lowest value:
var n = 8; // Number to match
var l = [3, 7, 12, 19]; // List of values
var greater = l.where((e) => e >= n).toList()..sort(); //List of the greater values
print(greater.first); // Print the first value. -> 12
To get Closest Value of number
import 'dart:math';
import 'dart:collection';
void main(){
List<double> value = [1,4,6,3,7,9,12,34,12,-12,-91];
print(value.getCloseValue(8)); // 7
print(value.getCloseValue(6)); // 6
print(value.getCloseValue(-11)); // -12
}
extension on List<num> {
num getCloseValue(num x) {
if (isEmpty) return 0;
Map<num, num> values = {};
forEach((e) {
values[e] = (e - x).abs();
});
var sortedKeys = values.keys.toList(growable:false)
..sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
final sortedMap = LinkedHashMap
.fromIterable(sortedKeys, key: (k) => k, value: (k) => values[k]);
return sortedMap.keys.first;
}
}
List<int> arr = [6, 12, 11, 18, 24,5,6,99,10,9];
arr.sort((a, b) => a.compareTo(b));
print(arr);
print(Utils.getNextLargerNumber(8, arr));
and below is the logic:
static int getNextLargerNumber(int number, List<int> array)
{
for (var i = 0; i < array.length; i++) {
if (number < array[i]) {
return array[i];
}
}
return -1;
}
Mattia's answer is already good enough. (although the list cant have the length 0 and it might be not as efficient, as you have a where() as well as sort() in there). Here is a different approach, that solves those concerns:
Nearest value to target (larger favored)
final nearestLarger = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() < (b -target).abs() ? a : b);
Nearest value to target (smaller favoured)
final nearestSmaller = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() <= (b -target).abs() ? a : b);
Note that both functions retrieve the nearest value to the target, but in case of ambiguity (eg. [3,4,5]) either the bigger or smaller value is favored.
Is there a better/faster way in Dart to rotate a list?
List<Object> rotate(List<Object> l, int i) {
i = i % l.length;
List<Object> x = l.sublist(i);
x.addAll(l.sublist(0, i));
return x;
}
Could be simplified a bit
List<Object> rotate(List<Object> list, int v) {
if(list == null || list.isEmpty) return list;
var i = v % list.length;
return list.sublist(i)..addAll(list.sublist(0, i));
}
If you want to shift instead of rotate you can simply use the removeAt function:
List<int> list = [ 1, 2, 3 ];
int firstElement = list.removeAt(0);
print(list); // [ 2, 3 ]
print(firstElement); // 1
From the docs:
Removes the object at position [index] from this list.
This method reduces the length of this by one and moves all later objects down by one position.
Returns the removed value.
The [index] must be in the range 0 ≤ index < length. The list must be growable.
Here are some more useful JS shims.