extract common elements from lists in dart - flutter

i have 3 Lists, for example:
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
and i expect the common elements:
// [7,99,21]
here is what i've tried but didn't work correctly:
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
List common = l1;
l2.forEach((element) {
l3.forEach((element2) {
if (!common.contains(element) || !common.contains(element2)) {
common.remove(element);
common.remove(element2);
}
});
});
print(common);
plus, the number of lists is dynamic, so i expect to nest them like this, i have no experience with recursion so i couldn't do it or even know if it's better than nesting loops.
thanks for helping.

You don't need nested loops or recursion for this. Dart has Sets and a very nice fold method on Lists.
main() {
final lists = [
[1, 2, 3, 55, 7, 99, 21],
[1, 4, 7, 65, 99, 20, 21],
[0, 2, 6, 7, 21, 99, 26]
];
final commonElements =
lists.fold<Set>(
lists.first.toSet(),
(a, b) => a.intersection(b.toSet()));
print(commonElements);
}
Gives:
{7, 99, 21}
Further, this can be used no matter how many lists are contained in lists.

One solution :
void main() {
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
l1.removeWhere((item) => !l2.contains(item));
l1.removeWhere((item) => !l3.contains(item));
print(l1);
}
Result :
[7, 99, 21]
If your number of lists is dynamic, then a solution is to count all occurences within all the lists, and retains only values where number of occurence is equals to the number of lists :
void main() {
List<List> lists = [
[1, 2, 3, 55, 7, 99, 21],
[1, 4, 7, 65, 99, 20, 21],
[0, 2, 6, 7, 21, 99, 26]
];
Map map = Map();
for (List l in lists) {
l.forEach((item) => map[item] = map.containsKey(item) ? (map[item] + 1) : 1);
}
var commonValues = map.keys.where((key) => map[key] == lists.length);
print(commonValues);
}
Result :
(7, 99, 21)

A function to copy and paste in your project:
List<T> intersection<T>(Iterable<Iterable<T>> iterables) {
return iterables
.map((e) => e.toSet())
.reduce((a, b) => a.intersection(b))
.toList();
}
final commonElements = intersection(lists);

In case, if you want to use nesting loops.
void main() {
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
List result = [];
for (final e1 in l1) {
for (final e2 in l2) {
for (final e3 in l3) {
if (e1 == e2 && e1 == e3) {
result.add(e1);
}
}
}
}
print(result);
}

Or you could do:
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
List uniqueItemsList = l1
.toSet()
.where((x) => l2.toSet().contains(x))
.where((x) => l3.toSet().contains(x))
.toList();
print(uniqueItemsList); //[7, 99, 21]

void main(){
List l1 = [1, 2, 3, 55, 7, 99, 21];
List l2 = [1, 4, 7, 65, 99, 20, 21];
List l3 = [0, 2, 6, 7, 21, 99, 26];
print(Set.from(l1).intersection(Set.from(l2)).intersection(Set.from(l3)).toList());
}

Related

How do I compare List<List<int>> to exist in other List<List<int>>

I want to know in Flutter if my sequence exists in the other sequenceTwo. For the example, I made two identical List<List<int>> that work. But I also want to know if it exists even if there are more record before or after the sequence as in the next check I do in the code below.
List<List<int>> sequence = [];
sequence.add(Uint8List.fromList([42, 6, 1, 8, 6, 63, 13, 10]));
sequence.add(Uint8List.fromList([42, 6, 1, 8, 9, 66, 13, 10]));
sequence.add(Uint8List.fromList([42, 6, 1, 8, 0, 57, 13, 10]));
sequence.add(Uint8List.fromList([42, 6, 1, 8, 3, 60, 13, 10]));
List<List<int>> sequenceTwo = [];
sequenceTwo.add(Uint8List.fromList([42, 6, 1, 8, 6, 63, 13, 10]));
sequenceTwo.add(Uint8List.fromList([42, 6, 1, 8, 9, 66, 13, 10]));
sequenceTwo.add(Uint8List.fromList([42, 6, 1, 8, 0, 57, 13, 10]));
sequenceTwo.add(Uint8List.fromList([42, 6, 1, 8, 3, 60, 13, 10]));
Function deepEqOne = const DeepCollectionEquality().equals;
debugPrint(
'DeepCollection: ' + deepEqOne(sequence, sequenceTwo).toString()); // true so works!
sequenceTwo.add(Uint8List.fromList([42, 6, 1, 9, 3, 60, 13, 10]));
debugPrint(
'DeepCollection: ' + deepEqOne(sequence, sequenceTwo).toString()); // false but I want this also to work somehow

Feel the "need for speed" Using reduce(into:_:) to count elements in enclosing array of sets of triplet elements

given this example array of triplets, real arrays would be very large data sets, hence the "need for speed":
let usedIndicies2 = [
[0, 1, 2]
[2, 1, 3],
[1, 4, 3],
[3, 4, 5],
[6, 7, 8],
[8, 7, 9],
[7, 10, 9],
[9, 10, 11],
[12, 2, 13],
[13, 2, 14],
[2, 3, 14],
[14, 3, 15],
[3, 5, 15],
[15, 5, 16],
[5, 17, 16],
[16, 17, 18],
[19, 8, 20],
[20, 8, 21],
[8, 9, 21],
[21, 9, 22],
[9, 11, 22],
[22, 11, 23],
[11, 24, 23],
[23, 24, 25],
[13, 14, 26],
[26, 14, 27],
[14, 15, 27],
[27, 15, 28],
[15, 16, 28],
[28, 16, 29],
[16, 18, 29],
[29, 18, 30],
[18, 20, 30],
[30, 20, 31],
[20, 21, 31],
[31, 21, 32],
[21, 22, 32],
[32, 22, 33],
[22, 23, 33],
[33, 23, 34],
[26, 27, 35],
[35, 27, 36],
[27, 28, 36],
[36, 28, 37],
[28, 29, 37],
[37, 29, 38],
[29, 30, 38],
[38, 30, 39],
[30, 31, 39],
[39, 31, 40],
[31, 32, 40],
[40, 32, 41],
[32, 33, 41],
[41, 33, 42],
[33, 34, 42],
[42, 34, 43],
[44, 35, 45],
[45, 35, 46],
[35, 36, 46],
[46, 36, 47],
[36, 37, 47],
[47, 37, 48],
[37, 38, 48],
[48, 38, 49],
[38, 39, 49],
[49, 39, 50],
[39, 40, 50],
[50, 40, 51],
[40, 41, 51],
[51, 41, 52],
[41, 42, 52],
[52, 42, 53],
[42, 43, 53],
[53, 43, 54],
[43, 55, 54],
[54, 55, 56],
]
Using swift, find the counts of each element of this type of array, while preserving the triplets, so the output would look like this:
let keyValuePairs =[
[[0: 1], [1: 3], [2: 5]],
[[2: 5], [1: 3], [3: 6]],
[[1: 3], [4: 2], [3: 6]],
[[3: 6], [4: 2], [5: 4]],
[[6: 1], [7: 3], [8: 5]],
[[8: 5], [7: 3], [9: 6]],
[[7: 3], [10: 2], [9: 6]],
[[9: 6], [10: 2], [11: 4]],
// etc. ...
]
I am only suggesting "reduce(into" as it feels like it is possible, but it maybe something else entirely that is better/faster/stronger.
(does not have to preserve the order of the triplet sets, but must preserver the order of elements inside the triplet: for instance the first and second one needs to stay [[0:x], [1:x], [2:x]], [[2:x], [1:x], [3:x]], or as an example the order could [[2:x], [1:x], [3:x]], [[0:x], [1:x], [2:x]] instead.
So far I've been able to produce the correct organization using this code below, it feels like this could be solved with reduce(into:_:) but I couldn't correctly "count" the elements.. i've left the code in that doesn't count correctly, obviously because it is intialized each time, but wanted to show what I had so far:
let keyValuePairs = usedIndicies2.reduce(into: [[[UInt32:Int]]]()) { (array, entry) in
var dict0:[UInt32:Int] = [UInt32:Int]()
var dict1:[UInt32:Int] = [UInt32:Int]()
var dict2:[UInt32:Int] = [UInt32:Int]()
dict0[entry[0], default: 0] += 1
dict1[entry[1], default: 0] += 1
dict2[entry[2], default: 0] += 1
var array012:[[UInt32:Int]] = [[UInt32:Int]]()
array012.append(dict0)
array012.append(dict1)
array012.append(dict2)
array.append(array012)
}
print("keyValuePairs:",keyValuePairs)
the output of this partially working code looks like this:
let keyValuePairs** = [
[[0: 1], [1: 1], [2: 1]],
[[2: 1], [1: 1], [3: 1]],
[[1: 1], [4: 1], [3: 1]],
[[3: 1], [4: 1], [5: 1]],
[[6: 1], [7: 1], [8: 1]],
[[8: 1], [7: 1], [9: 1]],
[[7: 1], [10: 1], [9: 1]],
[[9: 1], [10: 1], [11: 1]],
// etc...
]
would greatly appreciate your insights
Two steps:
Flatten the array and just make an ordinary histogram (count) for all values (that's a one-liner).
Now go back to the original array and map it into the array of pairs.
To demonstrate, I'll just operate on the opening piece of your data just to prove it works. I've given my own interpretation of the notion of a key value pair (I've used a tuple with labels), but feel free to patch that up as desired.
let original = [[0, 1, 2], [2, 1, 3], [1, 4, 3], [3, 4, 5]]
// step 1
var histo = [Int:Int]()
original.flatMap {$0}.forEach {histo[$0, default:0] += 1}
// step 2
let output = original.map {array in array.map {i in (item:i, count:histo[i]!)}}
Result:
[[(item: 0, count: 1), (item: 1, count: 3), (item: 2, count: 2)],
[(item: 2, count: 2), (item: 1, count: 3), (item: 3, count: 3)],
[(item: 1, count: 3), (item: 4, count: 2), (item: 3, count: 3)],
[(item: 3, count: 3), (item: 4, count: 2), (item: 5, count: 1)]]
And that is correct.

How to manage the hidden state dims when using pad_sequence?

Using Pytorch LSTM architecture trying to build a text generation model. For every batch, I'm using pad_sequence to have min padding for every sequence, therefore I have a variable dims batch (batch_size * seq_len). I'm applying also pack_padded_seq to only give the non-zero (non-padding) tokens to the LSTM. But, the variable dims batch throws an error while feeding it to the LSTM as following; Expected hidden[0] size (1, 8, 16), got (1, 16, 16). In this error, I have provided batch size 16 with 8 tokens for every sequence, but the hidden state is 16 * 16.
I have tried to create the hidden state in the forward function, but that did not work well. How can I create the hidden state such that it can accept variable dims batch and it will not be lost for the whole epoche?
class RNNModule(nn.Module):
def __init__(self, n_vocab, seq_size, embedding_size, lstm_size):
super(RNNModule, self).__init__()
self.seq_size = seq_size
self.lstm_size = lstm_size
self.embedding, num_embeddings, embedding_dim = create_emb_layer(weight_matrix, False)
self.lstm = nn.LSTM(embedding_size,
lstm_size,
num_layers=flags.n_layers,
batch_first=True
)
self.dense = nn.Linear(lstm_size, n_vocab)
def forward(self, x,length,prev_state):
embed = self.embedding(x)
packed_input = db.pack_src(embed,length)
packed_output, state = self.lstm(packed_input,prev_state)
padded,_ = db.pad_pack(packed_output)
logits = self.dense(padded)
return logits, state
def zero_state(self, batch_size = flags.batch_size):
return (torch.zeros(flags.n_layers, batch_size, self.lstm_size),
torch.zeros(flags.n_layers, batch_size, self.lstm_size))
input: tensor([[ 19, 9, 4, 3, 68, 8, 6, 2],
[ 19, 9, 4, 3, 7, 8, 6, 2],
[ 3, 12, 17, 10, 6, 40, 2, 0],
[ 4, 3, 109, 7, 6, 2, 0, 0],
[ 188, 6, 7, 18, 3, 2, 0, 0],
[ 4, 3, 12, 6, 7, 2, 0, 0],
[ 6, 7, 3, 13, 2, 0, 0, 0],
[ 3, 28, 17, 69, 2, 0, 0, 0],
[ 6, 3, 12, 11, 2, 0, 0, 0],
[ 3, 13, 6, 7, 2, 0, 0, 0],
[ 3, 6, 7, 13, 2, 0, 0, 0],
[ 6, 3, 23, 7, 2, 0, 0, 0],
[ 3, 28, 10, 2, 0, 0, 0, 0],
[ 6, 3, 23, 2, 0, 0, 0, 0],
[ 3, 6, 37, 2, 0, 0, 0, 0],
[1218, 2, 0, 0, 0, 0, 0, 0]])
Zero tokens are padding.
Embedding size: 64
LSTM size: 16
batch size: 16
The size of the hidden state you create has the correct size, but your input does not. When you pack it with nn.utils.rnn.pack_padded_sequence you've set batch_first=False, but your data has size [batch_size, seq_len, embedding_size] when you pass it to the packing, so that has batch_size as the first dimension. Also for the LSTM you use batch_first=True, which is appropriate for your data.
You only need to pack it correctly by setting batch_first=True as well, to match the order of your data.
rnn_utils.pack_padded_sequence(embed,length,batch_first=True)

matlab structures finding duplicates in one field to search through another field

I have a large structure with many fields but I need to find the index of the min magnitude at each time interval.
Structure(:).Time = [ 1, 1, 1, 1, 1, 11, 11, 21, 21, 21, 31, 31, 31, 31, 31, ...]
Structure(:).Mag = [ 11, 16, 9, 4, 6, 111, 10, 8, 15, 3, 0, 95, 52, 16, 7, ...]
So the solution should be:
Solutionindex = [ 4, 7, 10, 11, ...]
To correspond with time = 1, Mag = 4; time = 11, Mag = 10; time = 21, Mag = 3; time = 31, Mag = 0.
This sounds like a job for accumarray (and its trusty sidekick unique)!
% Sample data:
Structure = struct('Time', { 1, 1, 1, 1, 1, 11, 11, 21, 21, 21, 31, 31, 31, 31, 31}, ...
'Mag', {11, 16, 9, 4, 6, 111, 10, 8, 15, 3, 0, 95, 52, 16, 7});
[timeVals, ~, index] = unique([Structure(:).Time]); % Find an index for unique times
nTimes = cumsum(accumarray(index, 1)); % Count the number of each unique time
Solutionindex = accumarray(index, [Structure(:).Mag].', [], #(x) find(x == min(x), 1)) + ...
[0; nTimes(1:(end-1))];
And the result:
Solutionindex =
4
7
10
11
With unique, you can get the different time intervals, then some logic and find. In find the second argument is number of indices to return. This is set to 1 to return the first index. If the last index is wanted, add , 'last' behind the 1.
Time = [ 1, 1, 1, 1, 1, 11, 11, 21, 21, 21, 31, 31, 31, 31, 31];
Mag = [ 11, 16, 9, 4, 6, 111, 10, 8, 15, 3, 0, 95, 52, 16, 7];
[uniques,idx] = unique(Time);
Solutionindex = zeros(1,length(uniques));
for ii=1:length(uniques)
Solutionindex(ii) = find(Mag(Time==uniques(ii)) == min(Mag(Time==uniques(ii))),1)+idx(ii)-1;
end
Result:
Solutionindex =
4 7 10 11

how to print string in a dictionary on swift?

How can I print type of largest number in this dictionary?
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var typeoflargest:String = " "
for (kind, numbers) in interestingNumbers {
for type in kind.characters {
for number in numbers {
if number > largest {
largest = number
typeoflargest = String(type)
}
}
}
}
print(largest)
print(typeoflargest)
output:
25
S
why I got only first character "S" instead of "Square"?
There is no reason to be iterating the characters of the kind string. Just do the following:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var typeoflargest:String = ""
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
typeoflargest = kind
}
}
}
print(largest)
print(typeoflargest)
Output:
25
Square
Alternative approach:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
let maximum = interestingNumbers
.map{ type, numbers in return (type: type, number: numbers.max()!) }
.max(by: { $0.number < $1.number })!
print(maximum.type, maximum.number)
Explanation:
First, get the maximal element of each category. Do this by iterating the dictionary, mapping the values from arrays of numbers to maximum numbers (within their respective arrays), yielding:
[
(type: "Square", number: 25), // 25 is the max of [1, 4, 9, 16, 25]
(type: "Prime", number: 13), // 13 is the max of [2, 3, 5, 7, 11, 13]
(type: "Fibonacci", number: 8) // 8 is the max of [1, 1, 2, 3, 5, 8]
]
Then, get the maximal type/number pair, by comparing their numbers, yielding the result:
(type: "Square", number: 25) // 25 is the max of 25, 13, 8