Search in dictionary on a variety of conditions Swift - swift

I have simple dictionary
var countOfR = ["R0": 0, "R1": 0, "R2": 0, "R3": 0, "R4": 0, "R5": 0, "R6": 0]
I need to check this dictionary by multiple conditions. For example, next statement works perfectly:
for index in countOfR {
if index == ("R0",2) || index == ("R1",2) || index == ("R2",2) || index == ("R3",2) || index == ("R4",2) || index == ("R5",2) || index == ("R6",2) {
type = "P"
This will find one "pair". But next I need to check for "two pairs" - "PP". It's terrible to write something like this:
if index == ("R0",2) && index == ("R1",2) || index == ("R0",2) && index == ("R2",2) || index == ("R0",2) && index == ("R3",2) || index == ("R0",2) && index == ("R4",2) || index == ("R0",2) && index == ("R5",2) || index == ("R0",2) && index == ("R6",2) || ...
and so on... I also need to search for "pair and trine", "three pairs" and many others.
For better understanding:
["R0": 1, "R1": 2, "R2": 1, "R3": 1, "R4": 0, "R5": 1, "R6": 0] is "P",
["R0": 1, "R1": 0, "R2": 0, "R3": 1, "R4": 0, "R5": 2, "R6": 0] is "P" too,
["R0": 1, "R1": 0, "R2": 2, "R3": 1, "R4": 0, "R5": 2, "R6": 0] is "PP"
How can I solve this task? Please, give me some advice!

Your something like this makes no sense as it never gets true. Your index (or what name it might be) cannot be equal to two different things at the same time.
I guess you just need to count the number of entries whose value is 2.
You can write something like this:
func getType(_ countOfR: [String: Int]) -> String {
let pairs = countOfR.filter{$0.value == 2}.count
let trines = countOfR.filter{$0.value == 3}.count
let type = String(repeating: "P", count: pairs) + String(repeating: "T", count: trines)
return type
}
print(getType(["R0": 1, "R1": 2, "R2": 1, "R3": 1, "R4": 0, "R5": 1, "R6": 0]))
//->P
print(getType(["R0": 1, "R1": 0, "R2": 0, "R3": 1, "R4": 0, "R5": 2, "R6": 0]))
//->P
print(getType(["R0": 1, "R1": 0, "R2": 2, "R3": 1, "R4": 0, "R5": 2, "R6": 0]))
//->PP

Create a dictionary with your conditions, and filter the main dictionary by comparing the condition dictionary. Type will be create based on the filtered result count.
var condition = ["R0":2,"R1":2,"R2":2,"R3":2,"R4":2,"R5":2,"R6":2]
let test1 = ["R0": 1, "R1": 2, "R2": 1, "R3": 1, "R4": 0, "R5": 1, "R6": 0]// is "P",
let count1 = test1.filter { index in condition.contains(where: { $0 == index }) }.count
let type1 = String(repeating: "P", count: count1)
print(type1)//P
let test2 = ["R0": 1, "R1": 0, "R2": 0, "R3": 1, "R4": 0, "R5": 2, "R6": 0]// is "P" too,
let count2 = test2.filter { index in condition.contains(where: { $0 == index }) }.count
let type2 = String(repeating: "P", count: count2)
print(type2)//P
let test3 = ["R0": 1, "R1": 0, "R2": 2, "R3": 1, "R4": 0, "R5": 2, "R6": 0]// is "PP"
let count3 = test3.filter { index in condition.contains(where: { $0 == index }) }.count
let type3 = String(repeating: "P", count: count3)
print(type3)//PP

Related

Logical indexing with two conditions

I have a rankingMat which contains the rankings of equity tickers, where every column represents one ticker and every row represents a point in time. The ranking has been performed in a descending manner, i.e. a 1 in rankingMat identifies the highest rank for that time period (read: row). Ticker/column 4 represents a cash security. This will be important further down the road.
Now, I would like to identify in which equity tickers I am supposed to invest. There exists two conditions:
I only invest in tickers that have a rank less or equal to 3.
In addition, I only invest in tickers that are ranked higher or equal compared to cash (ticker/column 4).
I'm able to get a result that fulfills the first condition:
rankingMat = ...
[NaN, NaN, NaN, NaN, NaN, NaN; ...
1, 5, 2, 3, 6, 4; ...
4, 5, 2, 3, 6, 1; ...
4, 1, 2, 5, 6, 3; ...
6, 4, 5, 2, 1, 3; ...
2, 3, 4, 6, 1, 5; ...
3, 6, 4, 1, 2, 5; ...
2, 5, 6, 1, 4, 3];
portfolio = rankingMat <= 3;
The result looks like this:
portfolio = ...
[0, 0, 0, 0, 0, 0; ...
1, 0, 1, 1, 0, 0; ...
0, 0, 1, 1, 0, 1; ...
0, 1, 1, 0, 0, 1; ...
0, 0, 0, 1, 1, 1; ...
1, 1, 0, 0, 1, 0; ...
1, 0, 0, 1, 1, 0; ...
1, 0, 0, 1, 0, 1]
My problem is condition 2. In every row, I need to compare not only if the integer is less or equal to 3, I also need to make sure that it is less than the integer in column 4 in that particular row. I am looking for a solution that avoids a for-loop. I guess it is possible with indexing. So, any hint is highly appreciated.
The final result should look like this:
portfolio = ...
[0, 0, 0, 0, 0, 0; ...
1, 0, 1, 1, 0, 0; ...
0, 0, 1, 1, 0, 1; ...
0, 1, 1, 0, 0, 1; ...
0, 0, 0, 1, 1, 0; ...
1, 1, 0, 0, 1, 0; ...
0, 0, 0, 1, 0, 0; ...
0, 0, 0, 1, 0, 0]
% Prior to R2016b
portfolio = rankingMat <= 3 & ...
bsxfun(#lt, rankingMat, rankingMat(:,4));
% On or after R2016b
portfolio = rankingMat <= 3 & ...
rankingMat < rankingMat(:,4);

How to remove multiple items from a swift array?

For example i have an array
var array = [1, 2, 3, 4]
I want to remove item at index 1 then at index 3 "let it be in a for loop".
But removing the item at index 1 will move the item at index 3 to index 2, thus messing up the second removal.
Any suggestions ?
Given your array
var numbers = [1, 2, 3, 4]
and a Set of indexes you want to remove
let indexesToRemove: Set = [1, 3]
You want to remove the values "2" and "4".
Just write
numbers = numbers
.enumerated()
.filter { !indexesToRemove.contains($0.offset) }
.map { $0.element }
Result
print(numbers) // [1, 3]
It's simple. delete items from the end.
First delete 3 and after that delete 1
Swift 3: Use swift closure to perform the same operation.
If your array is like
var numbers = [0, 1, 2, 3, 4, 5]
and indexes you want to remove
let indexesToBeRemoved: Set = [2, 4]
numbers = numbers
.enumerated()
.filter { !indexesToRemove.contains($0.offset) }
.map { $0.element }
and result
print(numbers) // [0, 1, 3, 5]
Swift 3:
Here is same operation with JSON Object (dictionary)
var arrayString = [
[ "char" : "Z" ],
[ "char" : "Y" ],
[ "char" : "X" ],
[ "char" : "W" ],
[ "char" : "V" ],
[ "char" : "U" ],
[ "char" : "T" ],
[ "char" : "S" ]
]
let arrayIndex = [2, 3, 5]
arrayString = arrayString.enumerated()
.filter { !arrayIndex.contains($0.0 + 1) }
.map { $0.1 }
print(arrayString)
[["char": "Z"], ["char": "W"], ["char": "U"], ["name": "T"], ["name":
"S"]]

How do I reproduce this mathematica code for calculating the transition matrix of pagerank on matlab?

So the formula that needs to be implemented is:
P = ((1 - delta)/n) + ((delta)*(A)ij / (Sigma(k=1 to n)(A)ik))
where delta = 0.85
n = 8
and A = the adjacency matrix for web pages being surfed
The mathematica code for it is:
A = {{1, 1, 1, 0, 0, 1, 0, 1}, {0, 0, 1, 0, 0, 1, 0, 1}, {1, 1, 0, 1,
0, 1, 1, 0}, {0, 1, 1, 0, 1, 0, 1, 0}, {1, 1, 1, 1, 0, 1, 1,
1}, {1, 1, 1, 0, 0, 1, 1, 0}, {1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0,
0, 1, 0, 0, 1}};
n = 8;
\[Delta] = 0.85;
P = Transpose[Table[(1 - \[Delta])/n + (\[Delta]*A[[i, j]])/(Sum[A[[i, k]], {k, 1, n}]), {i, 1, n}, {j, 1, n}]];
Everything else is just plugging in numbers.
Now the main problem I seem to have is getting the A[[i,j]]/Sum[A[i,k]] to work on matlab.
On matlab: when I input A[[i,j]] as A, and sum[A[i,k]] as either (sum(A,2))' or sum(A,1), the P that gets output on matlab becomes a column vector rather than an 8 x 8 matrix.
What am I missing?
There are many ways of doing it. I'll show you one way of using native vectorized MATLAB code, so no need for for-loops or arrayfun or anything like that.
A = [1, 1, 1, 0, 0, 1, 0, 1; 0, 0, 1, 0, 0, 1, 0, 1; 1, 1, 0, 1, 0, 1, 1, 0; 0, 1, 1, 0, 1, 0, 1, 0; 1, 1, 1, 1, 0, 1, 1, 1; 1, 1, 1, 0, 0, 1, 1, 0; 1, 0, 1, 0, 1, 0, 1, 0; 0, 0, 0, 0, 1, 0, 0, 1];
n = size(A, 1);
delta = 0.85;
% First, sum up all columns in each row
rowSums = sum(A,2);
% Then replicate them because the entries in each row of the vector are valid for every column in that specific row. So replicate them so that the output-matrix matches the size of A so we can work element-wise division later
rowSums2 = repmat(rowSums, 1, n);
% Use vectorized code, ./ will yield element-wise division as A and rowSums2 are of the same size now
P = (1 - delta)/n + delta*A ./ rowSums2
I hope I got the desired output right.

Solve matrix with parameters

I was trying to solve a matrix with parameters in matlab. So i defined a and b with syms a b and then my matrix D = [-1 -2 2 1 -3; 1 1 a 1 2; 2 1 -1 b 3; 1 1 -1 1 2; -1 1 a -1-b 0]
D =
[ -1, -2, 2, 1, -3]
[ 1, 1, a, 1, 2]
[ 2, 1, -1, b, 3]
[ 1, 1, -1, 1, 2]
[ -1, 1, a, - b - 1, 0]
When i do rref(D) it gives me the following:
>> rref(D)
ans =
[ 1, 0, 0, 0, 1]
[ 0, 1, 0, 0, 1]
[ 0, 0, 1, 0, 0]
[ 0, 0, 0, 1, 0]
[ 0, 0, 0, 0, 0]
This actually useless for me, because i need the system solved with the resulting parameters in it.
Anyone an idea? Thanks in advance!
well, it is pretty obvious that both a and b can be eliminated using rref, since a appears twice only in the 2nd col, and b appears twice only in the 4th col. For example, (row2+row3)/(row5+row1) and bingo, no a and b ...

mapReduce gives different results in upgraded 2.2.0

I've been using mongodb 2.0.4 in development, and on deploying to production I failed to realize they were running 2.2.0. The mapReduce function that I was using is no longer behaving as it was under 2.0.4, and I can't figure out why.
mongodb 2.0.4 (note: M,F,T,I,C,H,R,D should total 144, and does in this example):
{
"_id" : "",
"value" : {
"tag" : "",
"networth" : 43558505,
"land" : 201837,
"alive" : 144,
"M" : 86,
"F" : 6,
"T" : 5,
"I" : 10,
"C" : 17,
"H" : 4,
"R" : 12,
"D" : 4,
"gdi" : 15
}
}
mongo 2.2.0(m+f+t+i+c+h+r+d totals up to 108, when it should total 144)
{
"_id" : "",
"value" : {
"tag" : "",
"networth" : 43558505,
"land" : 201837,
"alive" : 144,
"M" : 67,
"F" : 5,
"T" : 3,
"I" : 6,
"C" : 13,
"H" : 3,
"R" : 9,
"D" : 2,
"gdi" : 15
}
}
Here is the map/reduce functions I'm using:
// Map function
var map = function() {
var key = this.tag;
var value =
{
tag: this.tag,
networth: this.networth,
land: this.land,
alive: this.alive,
gdi: this.gdi,
gov: this.gov
};
emit(key, value);
};
Reduce function
var reduce = function(k,vals) {
reducedVals = { tag: k, networth: 0, land: 0, alive: 0, M: 0, F: 0, T: 0, I: 0, C: 0, H: 0, R: 0, D: 0, gdi: 0 };
for (var i = 0; i < vals.length; i++){
reducedVals.networth += vals[i].networth;
reducedVals.land += vals[i].land;
reducedVals.alive += vals[i].alive;
reducedVals.gdi += vals[i].gdi;
if (vals[i].gov == "M") reducedVals.M = reducedVals.M + 1;
if (vals[i].gov == "F") reducedVals.F = reducedVals.F + 1;
if (vals[i].gov == "T") reducedVals.T = reducedVals.T + 1;
if (vals[i].gov == "I") reducedVals.I = reducedVals.I + 1;
if (vals[i].gov == "C") reducedVals.C = reducedVals.C + 1;
if (vals[i].gov == "H") reducedVals.H = reducedVals.H + 1;
if (vals[i].gov == "R") reducedVals.R = reducedVals.R + 1;
if (vals[i].gov == "D") reducedVals.D = reducedVals.D + 1;
}
return reducedVals;
};
Perform the map reduce
collection.mapReduce(map, reduce, {out: {replace : 'alliances'}, query: {"alive":1}}, function(err, collection) {
// Mapreduce returns the temporary collection with the results
db.close();
});
So brief rundown.. the collection has a bunch of scores, in this format:
"alive" : 1,
"countryNumber" : 47,
"deleted" : 0,
"gdi" : 0,
"gov" : "C",
"land" : 20111,
"name" : "AtheistCelebratingXmas",
"networth" : 9793082,
"protection" : 0,
"rank" : 1,
"resetid" : 407,
"serverid" : 9,
"tag" : "Evolve",
"vacation" : 0
I'm essentially grouping by tag, summing up the networth, land and alive columns. Then checking the gov column for its value and summing up the totals of D,R,etc. Is there a particular reason I'm missing for why this won't work correctly in 2.2 vs 2.0.4? Either way, will the new aggregate commands do this more easily? I gave it a brief look over, and can get the group by tag, with sums for networth and alive columns to work--but wouldn't know where to begin with the gov column.
The shape of the object you emit from your map function must be the same as the object returned from your reduce function. This is because the results of a reduce call can get fed back into reduce when MongoDB decides to parallelize your map-reduce.
So you need to change your map to assemble the values to emit like this so they have the same structure as what's returned from reduce:
var value = {
"tag" : this.tag,
"networth" : this.networth,
"land" : this.land,
"alive" : this.alive,
"gdi" : this.gdi
};
value[this.gov] = 1;
and then update your reduce function accordingly.
BTW, given enough docs this would have failed in 2.0.4 as well. It's just that 2.2 uses different thresholds for when to parallelize.
I accepted JohnnyHK answer as he answered why my code was not working from one version to another; however, I felt I should post what I modified in the code to resolve the issue.
Map Function:
var map = function() {
var key = this.tag;
var fields = {
tag: this.tag,
networth: this.networth,
land: this.land,
alive: this.alive,
gdi: this.gdi,
M: 0,
F: 0,
T: 0,
I: 0,
C: 0,
H: 0,
R: 0,
D: 0
};
if (this.gov == "M") fields["M"] = 1
else fields["M"] = 0
if (this.gov == "F") fields["F"] = 1
else fields["F"] = 0
if (this.gov == "T") fields["T"] = 1
else fields["T"] = 0
if (this.gov == "I") fields["I"] = 1
else fields["I"] = 0
if (this.gov == "C") fields["C"] = 1
else fields["C"] = 0
if (this.gov == "H") fields["H"] = 1
else fields["H"] = 0
if (this.gov == "R") fields["R"] = 1
else fields["R"] = 0
if (this.gov == "D") fields["D"] = 1
else fields["D"] = 0
emit(key, fields);
};
Reduce Function:
var reduce = function(k,vals) {
reducedVals = { tag: k, networth: 0, land: 0, alive: 0, M: 0, F: 0, T: 0, I: 0, C: 0, H: 0, R: 0, D: 0, gdi: 0};
for (var i = 0; i < vals.length; i++){
reducedVals.networth += vals[i].networth;
reducedVals.land += vals[i].land;
reducedVals.alive += vals[i].alive;
reducedVals.gdi += vals[i].gdi;
reducedVals.M += vals[i].M;
reducedVals.F += vals[i].F;
reducedVals.T += vals[i].T;
reducedVals.I += vals[i].I;
reducedVals.C += vals[i].C;
reducedVals.H += vals[i].H;
reducedVals.R += vals[i].R;
reducedVals.D += vals[i].D;
}
return reducedVals;
};