How to get multiple random elements from list in Dart - dart

When i have list
[1, 2, 3, 4, 5, 6, 7]
i want to get 3 random elements from list
e.g
[1, 3, 4] or [4, 5, 1] or [3, 2, 5]
how can i solve that simply
is there any dart library??

The previous solution is good but could have been written in a more generic way so we don't loose the type information of the List. Also, take does not return a List but instead Iterable.
I have rewritten the code to be more generic and shorter by using the cascade operator. I am not sure if you want a List or Iterable as output so I have made multiple solutions:
void main() {
final items = [1, 2, 3, 4, 5, 6, 7];
print(pickRandomItems(items, 3)); // (7, 4, 3)
print(pickRandomItemsAsList(items, 3)); // [2, 4, 5]
print(pickRandomItemsAsListWithSubList(items, 3)); // [1, 3, 6]
print(items); // [1, 2, 3, 4, 5, 6, 7] (just to show that the original List is untouched)
}
Iterable<T> pickRandomItems<T>(List<T> items, int count) =>
(items.toList()..shuffle()).take(count);
List<T> pickRandomItemsAsList<T>(List<T> items, int count) =>
(items.toList()..shuffle()).take(count).toList();
List<T> pickRandomItemsAsListWithSubList<T>(List<T> items, int count) =>
(items.toList()..shuffle()).sublist(0, count);
Instead of using take in pickRandomItemsAsList you can instead use sublist. But the catch with subList is that if the length are greater than the List it will give an error but with take you just get all the elements in the List shuffled.

Simply shuffle list and take sublist (slice):
List pickRandomItems(List items, int count) {
final list = List.from(items); // cloning original list
list.shuffle(); // shuffling items
return list.take(count); // taking N items
}
List items = [1, 2, 3, 4, 5, 6, 7];
print(pickRandomItems(items, 3));

Related

How can i add an entire list on top of another list in Flutter

AddAll is pretty cool, but adds it at the bottom of the list.
I want to add the sorted list A on top of the sorted list B. I need list A for a different view
listA = [1, 2, 3];
listB = [4, 5, 6];
listB.addAll(listA);
// lista == [4, 5, 6, 1, 2, 3]
The easiest but maybe bad solution i can think of is to add first listA then listB to a listC.
listC = [];
listC.addAll(listA);
listC.addAll(listB);
//listc == [1, 2, 3, 4, 5, 6]
listB = []
listB.addAll(listC)
// garbage collector to gets rid of C
// listB == [1, 2, 3, 4, 5, 6];
// listA == [1, 2, 3];
This seems a bit inefficient, so I was wondering if there is a better way for this that doesn't include loops or anything thelike. Something like flutters 'addAt', like listB.addAllAt(0, listA)
To clarify, having a third list is a 'necessary evil' that i would like to avoid. I want one list that would be AB, and one list that is just A, to go back to the question, how do i add A on top of B.
While the suggest answer did not solve my issue, it gave me the right idea. I can add them with 'plus' into one of the original lists
listA = [1, 2, 3];
listB = [4, 5, 6];
listB = listA+listB;
// listB == [1, 2, 3, 4, 5, 6];
// listA == [1, 2, 3];
Thank you MendelG for the right idea!

Swift: Two-dimensional array error index out of range

I'm trying to add new item into two-dimensional array but I'm getting this error Index out of range
Here is my implementation:
var array = [[Int]]()
array[0][0] = 1 // <-- Index out of range error
Any of you knows why I'm getting this error or if there is work around ?
I really appreciate you help
You have declared an Array of Arrays of Ints.
To append something to that array, you have to create a new Array of Int to append to it.
After you have appended one or more Arrays of Int, you can then modify those values, or append additional Int values to the 2nd-level array:
var array = [[Int]]()
print(array)
// output is: []
// append an array of One Int
array.append([1])
print(array)
// output is: [[1]]
// append an array of Three Ints
array.append([1, 2, 3])
// append an array of Six Ints
array.append([4, 5, 6, 7, 8, 9])
print(array)
// output is: [[1], [1, 2, 3], [4, 5, 6, 7, 8, 9]]
// modify the value of the 2nd Int in the 2nd array
array[1][1] = 100
print(array)
// output is: [[1], [1, 100, 3], [4, 5, 6, 7, 8, 9]]
// append a new Int to the 2nd array
array[1].append(777)
print(array)
// output is: [[1], [1, 100, 3, 777], [4, 5, 6, 7, 8, 9]]

How to flatMap List in Dart?

I can map list in Dart:
[1,2,3].map((e) => e + 1)
but how can I flatMap this list?
Code presented below does not work.
[1,2,3].flatMap((e) => [e, e+1])
expand method is equivalent to flatMap in Dart.
[1,2,3].expand((e) => [e, e+1])
What is more interesting, the returned Iterable is lazy, and calls fuction for each element every time it's iterated.
Coming from Swift, flatMap seems to have a little different meaning than the OP needed. This is a supplemental answer.
Given the following two dimensional list:
final list = [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]];
You can convert it into a single dimensional iterable like so:
final flattened = list.expand((element) => element);
// (1, 2, 2, 3, 3, 3, 4, 4, 4, 4)
Or to a list by appending toList:
final flattened = list.expand((element) => element).toList();
// [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

What is the equivalent of this python dictionary in Dart?

What is the equivalent of this python dictionary in Dart?
edges = {(1, 'a') : 2,
(2, 'a') : 2,
(2, '1') : 3,
(3, '1') : 3}
You could use package:collection's EqualityMap to define a custom hash algorithim that uses ListEquality. For example, you could do this:
var map = new EqualityMap.from(const ListEquality(), {
[1, 'a']: 2,
[2, 'a']: 2,
});
assert(map[[1, 'a']] == map[[1, 'a']])
This will be a heavier weight implementation of Map, though.
You have differents way to do this
1. Using a List
var edges = <List, num>{
[1, 'a']: 2,
[2, 'a']: 2,
[2, '1']: 3,
[3, '1']: 3
};
Simple to write, but you won't be able to retrieve data with
edges[[2, 'a']]; // null
Except if you use const
var edges = const <List, num>{
const [1, 'a']: 2,
const [2, 'a']: 2,
const [2, '1']: 3,
const [3, '1']: 3
};
edges[const [2, 'a']]; // 2
2. Using Tuple package
https://pub.dartlang.org/packages/tuple
var edges = <Tuple2<num, String>, num>{
new Tuple2(1, 'a'): 2,
new Tuple2(2, 'a'): 2,
new Tuple2(2, '1'): 3,
new Tuple2(3, '1'): 3
}
edges[new Tuple2(2, 'a')]; // 2
var edges = {[1, 'a'] : 2,
[2, 'a'] : 2,
[2, '1'] : 3,
[3, '1'] : 3};
Except that you won't ever be able to look up those keys, because a new instance of [1, 'a'] will be a different object.

How to remove array elements and append it to the front of the array in ruby without using any inbuilt methods?

I have an array say [1,2,3,4,5,6,7,8]. I need to take an input from the user and remove the last input number of array elements and append it to the front of the array. This is what I have achieved
def test(number, array)
b = array - array[0...(array.length-1) - number]
array = array.unshift(b).flatten.uniq
return array
end
number = gets.chomp_to_i
array = [1,2,3,4,5,7,8,9]
now passing the argument to test gives me the result. However, there are two problems here. first is I want to find a way to do this append on the front without any inbuilt method.(i.e not using unshift).Second, I am using Uniq here, which is wrong since the original array values may repeat. So how do I still ensure to get the correct output? Can some one give me a better solution to this.
The standard way is:
[1, 2, 3, 4, 5, 7, 8, 9].rotate(-3) #=> [7, 8, 9, 1, 2, 3, 4, 5]
Based on the link I supplied in the comments, I threw this together using the answer to that question.
def test(number, array)
reverse_array(array, 0, array.length - 1)
reverse_array(array, 0, number - 1)
reverse_array(array, number, array.length - 1)
array
end
def reverse_array(array, low, high)
while low < high
array[low], array[high] = array[high], array[low]
low += 1
high -= 1
end
end
and then the tests
array = [1,2,3,4,5,7,8,9]
test(2, array)
#=> [8, 9, 1, 2, 3, 4, 5, 7]
array = [3, 4, 5, 2, 3, 1, 4]
test(2, array)
#=> [1, 4, 3, 4, 5, 2, 3]
Which I believe is what you're wanting, and I feel sufficiently avoids ruby built-ins (no matter what way you look at it, you're going to need to get the value at an index and set a value at an index to do this in place)
I want to find a way to do this append on the front without any inbuilt method
You can decompose an array during assignment:
array = [1, 2, 3, 4, 5, 6, 7, 8]
*remaining, last = array
remaining #=> [1, 2, 3, 4, 5, 6, 7]
last #=> 8
The splat operator (*) gathers any remaining elements. The last element will be assigned to last, the remaining elements (all but the last element) are assigned to remaining (as a new array).
Likewise, you can implicitly create an array during assignment:
array = last, *remaining
#=> [8, 1, 2, 3, 4, 5, 6, 7]
Here, the splat operator unpacks the array, so you don't get [8, [1, 2, 3, 4, 5, 6, 7]]
The above moves the last element to the front. To rotate an array n times this way, use a loop:
array = [1, 2, 3, 4, 5, 6, 7, 8]
n = 3
n.times do
*remaining, last = array
array = last, *remaining
end
array
#=> [6, 7, 8, 1, 2, 3, 4, 5]
Aside from times, no methods were called explicitly.
You could create a new Array with the elements at the correct position thanks to modulo:
array = %w[a b c d e f g h i]
shift = 3
n = array.size
p Array.new(n) { |i| array[(i - shift) % n] }
# ["g", "h", "i", "a", "b", "c", "d", "e", "f"]
Array.new() is a builtin method though ;)

Resources