I am migrating my data from 1 format to another for a large update to one of my iOS apps. This means that when a user updates their application it migrates their data to a new location. This new location has much stricter rules and uses proper practices (basically when I first created the app I was a noob and there are bad practices currently in the database and this new location is for good data only).
I have everything migrating nicely and everything works except I need to do one last thing. The large dictionary that I save to the database (it uses firebase fyi) has -1.0 stored everywhere there should be a nil value (bad, I know). What I need to do is loop through the entire dictionary and remove any key where the value of that key is -1.0.
The Dictionary is of type [AnyHashable : Any] which is what firebase uses.
I have tried this so far.
if let data = dataDictionary as? [AnyHashable : Any] {
let foundItems = data.filter { $0.value as? Double == -1.0 }
print(foundItems)
}
the plan was to then loop through that found items array and remove any key from the data dictionary that contained it.
This is what the data dictionary looks like:
"-KpIdh_TQMG4fyfFgkdt" = {
assignments = {
"-KpIgH6uN19OpcuedYe1" = {
assignmentGoal = "-1";
assignmentName = "Information System Proposal";
assignmentResult = 100;
assignmentWeight = 5;
};
"-KpIgJnFlC6fhgS0NWxF" = {
assignmentGoal = "-1";
assignmentName = "Information System";
assignmentResult = "-1";
assignmentWeight = 35;
};
"-KpIgOGSAwg_VSpDWhWR" = {
assignmentGoal = "-1";
assignmentName = "Process Analysis";
assignmentResult = "-1";
assignmentWeight = 30;
};
"-KpIgPhu_3Zxw36xt3O4" = {
assignmentGoal = "-1";
assignmentName = Labs;
assignmentResult = "-1";
assignmentWeight = 10;
};
"-KpIgQoFEdRnLlMAq2VN" = {
assignmentGoal = "-1";
assignmentName = Exam;
assignmentResult = "-1";
assignmentWeight = 20;
};
};
paperColor = 22;
paperGoal = 95;
paperName = "Systems Analysis";
};
};
semesterCode = 17S2;
semesterGoal = 90;
semesterName = "2017 Semester Two";
};
};
and this is what it should look like
"-KpIdh_TQMG4fyfFgkdt" = {
assignments = {
"-KpIgH6uN19OpcuedYe1" = {
assignmentName = "Information System Proposal";
assignmentResult = 100;
assignmentWeight = 5;
};
"-KpIgJnFlC6fhgS0NWxF" = {
assignmentName = "Information System";
assignmentWeight = 35;
};
"-KpIgOGSAwg_VSpDWhWR" = {
assignmentName = "Process Analysis";
assignmentWeight = 30;
};
"-KpIgPhu_3Zxw36xt3O4" = {
assignmentName = Labs;
assignmentWeight = 10;
};
"-KpIgQoFEdRnLlMAq2VN" = {
assignmentName = Exam;
assignmentWeight = 20;
};
};
paperColor = 22;
paperGoal = 95;
paperName = "Systems Analysis";
};
};
semesterCode = 17S2;
semesterGoal = 90;
semesterName = "2017 Semester Two";
};
};
The solution I have is to map (iterate) over each parent key and assign it's child nodes to a variable child. Then test each child property (assignmentGoal, assignmentName etc) for either "-1" for the string and -1 for the ints. If it's a match, remove that key: value pair from child.
Then assign child back to the parent node.
let result: [Any] = dict.map { dictionary in
var d = dictionary
var child = d.value as Dictionary
if let goal = child["assignmentGoal"] as? String, goal == "-1" {
child.removeValue(forKey: "assignmentGoal")
}
if let name = child["assignmentName"] as? String, name == "-1" {
child.removeValue(forKey: "assignmentName")
}
if let result = child["assignmentResult"] as? Int, result == -1 {
child.removeValue(forKey: "assignmentResult")
}
if let weight = child["assignmentWeight"] as? Int, weight == -1 {
child.removeValue(forKey: "assignmentWeight")
}
d.value = child
return d
}
//show the output
for item in result {
print(item)
}
and the result output
(key: "-KpIgOGSAwg_VSpDWhWR",
value: ["assignmentName": "Process Analysis System", "assignmentWeight": 30])
(key: "-KpIgQoFEdRnLlMAq2VN",
value: ["assignmentName": "Exam", "assignmentWeight": 20])
(key: "-KpIgJnFlC6fhgS0NWxF",
value: ["assignmentName": "Information System", "assignmentGoal": "3", "assignmentWeight": 35])
(key: "-KpIgPhu_3Zxw36xt3O4",
value: ["assignmentName": "Labs", "assignmentWeight": 10])
(key: "-KpIgH6uN19OpcuedYe1",
value: ["assignmentName": "Information System Proposal", "assignmentResult": 100, "assignmentWeight": 5])
Related
I know this question has been ask several times but none of the solutions work for me. here is my snap shot
Snap (CaseExtend) {
NYxdSlq8yOgQd3phssRlD = {
CaseMinute = {
WMKuImjuH0qPIGJhHHJKv = {
caseMinute = "";
dateTime = "Dec 1, 2021 12:20 PM";
minuteId = WMKuImjuH0qPIGJhHHJKv;
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
};
CaseParticipant = {
3f7nqmcWFTenePkEB9KoMHLzVtk2 = {
userId = 3f7nqmcWFTenePkEB9KoMHLzVtk2;
};
OtRFaqilTigWvEkUCASvCoEegny1 = {
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
};
caseId = Oj7TwzDC3HQMJKyTb8Ebi;
caseNumber = TEST;
court = "Labour Tribunal";
courtRoomNo = "";
date = "2021-12-01";
extendId = NYxdSlq8yOgQd3phssRlD;
extendStatus = "Not Extend";
location = "";
participantCount = 2;
profilePicture = "https://firebasestorage.googleapis.com/v0/b/lege-155e1.appspot.com/o/Profile%20Pictures%2FOtRFaqilTigWvEkUCASvCoEegny1.jpg?alt=media&token=676226fa-638b-4175-a8d5-247095f6b86a";
step = TBM;
time = "";
userId = OtRFaqilTigWvEkUCASvCoEegny1;
};
}
and i retrieve the snapshot using following code,
ref.child("CaseExtend").queryOrdered(byChild: "userId").queryEqual(toValue: "OtRFaqilTigWvEkUCASvCoEegny1" ).observe(.value, with: { (DataSnapshot) in
})
i want to add the caseID, caseNumber, date.. and other values for different variables. is there anyway i can do this?
first of all you are getting all data in casetExtend node all the variables you want to assign is not under that node. for that you need to navigate one level of child node.
ref.child("CaseExtend").queryOrdered(byChild: "userId").queryEqual(toValue: "OtRFaqilTigWvEkUCASvCoEegny1" ).observe(.value, with: { (snapshot) in
for caseSnapshot in snapshot.children.allObjects as! [DataSnapshot] {
let dict = caseSnapshot.value as? [String: AnyObject] // assign the snapshot to a dictionary
let court = dict!["court"] as? String ?? "unknown"; // assign the variable
}
})
I'm trying to get outline working with a custom language in VScode. I have the below code but I feel like it is slow because of the way I find a range in class. Are there better ways to find the range and assign children. I've thought about just keeping track of the depth of the brackets and assigning all functions/methods/classes in higher depths into the last item of previous depth.
It was based off of this answer.
class JSLDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
public provideDocumentSymbols(document: vscode.TextDocument,
token: vscode.CancellationToken): Thenable<vscode.DocumentSymbol[]> {
return new Promise((resolve, reject) => {
var symbols: vscode.DocumentSymbol[] = [];
var depth = 0;
for (var i = 0; i < document.lineCount; i++) {
var line = document.lineAt(i);
var txt = line.text;
var ltxt = txt.toLowerCase();
let open_brackets = ltxt.match(/\(/g) || [];
let close_brackets = ltxt.match(/\)/g) || [];
// console.log(ltxt)
// console.log(open_brackets, close_brackets)
//console.log(i, open_brackets.length, close_brackets.length)
depth += open_brackets.length - close_brackets.length;
//console.log(depth);
if (ltxt.includes("define class(")) {
let sname = txt.trim().substr(14, txt.trim().length - 16); //this is hard coded right now but it's kind of working
let detail = "ARGS:x, y returns z";
let start_pos = new vscode.Position(i, 0);
let n_bracket = 1;
let i_char = 0;
//let children: vscode.DocumentSymbol[] = []
let ds = new vscode.DocumentSymbol(sname, detail, vscode.SymbolKind.Class, line.range, line.range);
for(var i_line = i; n_bracket > 0; i_line++){
let class_line = document.lineAt(i_line);
let mtxt = class_line.text;
let ic;
if(i == i_line) ic = 16;
else ic = 0;
for(i_char = ic; i_char < mtxt.length; i_char++){
if(mtxt[i_char] === "(") n_bracket++;
else if(mtxt[i_char] === ")") n_bracket--;
if(n_bracket === 0) break
}
if (/(\w[\w\d\s]*)=\s*method\({((?:\s*(?:\w[\w\d\s]*)(?:=[^,]*)?,?\s*)*)},/i.test(mtxt)) {
let result = mtxt.match(/(\w[\w\d\s]*)=\s*method\({((?:\s*(?:\w[\w\d\s]*)(?:=[^,]*)?,?\s*)*)},/i)!;
let mname = result[1].trim();
let m_details = ""
if(result.length == 3){
m_details = result[2].trim();
}
ds.children.push(new vscode.DocumentSymbol(mname, m_details, vscode.SymbolKind.Method, class_line.range, class_line.range));
}
if(n_bracket === 0) break
}
let end_pos = new vscode.Position(i_line, i_char);
let rng = new vscode.Range(start_pos, end_pos);
ds.range = rng;
//ds.children = children;
symbols.push(ds);
}
else if (/(\w[\w\d\s]*)=\s*function\({((?:\s*(?:\w[\w\d\s]*)(?:=[^,]*)?,?\s*)*)},/.test(ltxt)) {
let result = txt.match(/(\w[\w\d\s]*)=\s*function\({((?:\s*(?:\w[\w\d\s]*)(?:=[^,]*)?,?\s*)*)},/i)!;
let sname = result[1].trim();
let detail = "";
if(result.length == 3){
detail = "(" + result[2].trim() + ")";
}
symbols.push(new vscode.DocumentSymbol(sname, detail, vscode.SymbolKind.Function, line.range, line.range));
}
}
resolve(symbols);
});
}
}
I have a dictionary. When I try to access that dictionary, it is returning a null value when it should definately be returning an actual value. I'm stumped. Any help is always appreciated.
if let d = response.result.value {
print(d) //prints correct data
let prices = d["prices"] as? [[String:AnyObject?]]
print(prices) //prints nil
let best_price = prices?[0]
let price = best_price?["price"] as? String
print(price) //prints nil
}
Console:
{
item = {
"item_number" = 57;
image = "http://example.com/tent.jpg";
name = "Small Red Tent";
};
prices = (
{
link = "http://example.com/id=19";
price = "58.15";
rating = "3.64";
"vendor_id" = 50;
},
{
link = "http://example.com/id=50";
price = "58.14";
rating = "5.00";
"vendor_id" = 110;
},
{
link = "http://example.com/id=26";
price = "50.40";
rating = "4.71";
"vendor_id" = 73;
},
{
link = "http://example.com/id=12";
price = "47.16";
rating = "4.00";
"vendor_id" = 1;
},
{
link = "http://example.com/id=13";
price = "45.75";
rating = "3.90";
"vendor_id" = 25;
},
{
link = "http://example.com/id=16";
price = "41.32";
rating = "3.02";
"vendor_id" = 16;
},
{
link = "http://example.com/id=1";
price = "36.59";
rating = "4.84";
"vendor_id" = 51;
},
{
link = "http://example.com/id=2";
price = "36.29";
rating = "3.26";
"vendor_id" = 43;
},
{
link = "http://example.com/id=13";
price = "34.59";
rating = "4.14";
"vendor_id" = 48;
},
{
link = "http://example.com/id=3";
price = "32.00";
rating = "4.29";
"vendor_id" = 53;
},
{
link = "http://example.com/id=4";
price = "24.50";
rating = "4.16";
"vendor_id" = 8;
},
{
link = "http://example.com/id=5";
price = "15.00";
rating = "4.87";
"vendor_id" = 39;
},
{
link = "http://example.com/id=6";
price = "0.00";
rating = "3.00";
"vendor_id" = 65;
}
);
}
nil
nil
So the solution was proposed by Larme solved the problem.
let prices = d["prices"] as? [AnyObject]
Although I never figured out why casting d["prices"] as? [[String:AnyObject?]] wouldn't also work.
Code
func downloadimages (URL: NSURL) {
let request = NSMutableURLRequest ( URL: URL)
request.HTTPMethod = "GET"
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error ) in
guard error == nil else {
print("we have an error from Server")
return
}
var JSONData: AnyObject!
do {
JSONData = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) /* as? [String:AnyObject?] */
} catch {
print (" We had a Parsing issue '\(data)'")
return
}
print(JSONData)// Doesn't print 'Optional' word?????
print(JSONData!)
if let something = JSONData!["photos"]{
print (something!)
print(something) // This prints the word 'Optional as well'
}
Output
//printed unwrapped--NOT GOOD! -- I didn't unwrap it with '!'
{
photos = {
page = 1;
pages = 622374;
perpage = 1;
photo = (
{
farm = 8;
id = 27765969370;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "8262787#N07";
secret = 6daeee7d68;
server = 7233;
title = "Stars, Planets and Lightning Bugs";
}
);
total = 622374;
};
stat = ok;
}
// unwrapped printed--Good!
{
photos = {
page = 1;
pages = 622374;
perpage = 1;
photo = (
{
farm = 8;
id = 27765969370;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "8262787#N07";
secret = 6daeee7d68;
server = 7233;
title = "Stars, Planets and Lightning Bugs";
}
);
total = 622374;
};
stat = ok;
}
//Unwrapped printed--Good
{
page = 1;
pages = 622374;
perpage = 1;
photo = (
{
farm = 8;
id = 27765969370;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "8262787#N07";
secret = 6daeee7d68;
server = 7233;
title = "Stars, Planets and Lightning Bugs";
}
);
total = 622374;
}
//wrapped and prints as optional--Good!
Optional({
page = 1;
pages = 622374;
perpage = 1;
photo = (
{
farm = 8;
id = 27765969370;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "8262787#N07";
secret = 6daeee7d68;
server = 7233;
title = "Stars, Planets and Lightning Bugs";
}
);
total = 622374;
})
My confusion is, if JSONData is an optional then why does it print as non-optional without ! and if it isn't an optional then why doesn't it give any error as Can not force unwrap value of non-optional type?. Since unwrapping a non-optional is error-ful!
My guess is that I am not understanding what my JSONData's type really is...
My guess is that I am not understanding what my JSONData's type really is...
I believe that is the point.
You've declared JSONData as AnyObject!, which is also known as ImplicitlyUnwrappedOptional<AnyObject>.
So, in your code print(JSONData), the value of JSONData is implicitly unwrapped.
And check the type of something in the Quick Help pane of your Xcode. It should be displayed as AnyObject?, aka Optional<AnyObject>.
One bad thing is that when implicit unwrapping occurs it doesn't get well-documented. You may need to know more about ImplicitlyUnwrappedOptional, before knowing exactly when that happens.
My problem is adding new numbers to the array field in users. all the code seems to work but i have the problem with saveAll function. All the names are correct, as i've checked on several different occasions.
func taskAllocation(){
var query = PFUser.query()
var objectQuery:[PFUser] = [PFUser]()
query.whereKey("Year", equalTo: yearTextField.text.toInt())
query.whereKey("Class", equalTo: classTextField.text.toInt())
query.whereKey("Keystage", equalTo: keystageTextField.text.toInt())
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
if error != nil {
println(error)
} else {
if objects.isEmpty {
println("empty query")
}
else {
for object in objects as [PFUser] {
var test:[Int] = object["taskIDs"] as [Int]
test.append(self.getIndex)
println(test)
object["taskIDs"] = test
object["tasksCompleted"] = "hello"
objectQuery.append(object)
}//For
println(objectQuery.count)
if objectQuery.count != 0{
println("Success!!!")
println(objectQuery)
PFUser.saveAllInBackground(objectQuery)
}
}
}
}
This below is stored in the println(objectQuery) as you can see the taskIDs have been appended and the tasksCompleted contains the string. Which leads me to believe that there is a problem with the saveallinbackground function.
[<PFUser: 0x155f6510, objectId: W6TrPQwCQ7, localId: (null)> {
Class = 2;
Forename = "Joe ";
Keystage = 2;
Surname = Freeston;
Year = 4;
admin = false;
completedTaskIDs = (
);
taskIDs = (
0,
2,
4,
5,
6,
46
);
tasksCompleted = hello;
tasksCorrect = 0;
userType = Student;
username = jfreeston;
}, <PFUser: 0x1569b7a0, objectId: slLd1KBIaM, localId: (null)> {
Class = 2;
Forename = "Camilla ";
Keystage = 2;
Surname = Linhart;
Year = 4;
admin = false;
completedTaskIDs = (
);
taskIDs = (
0,
46
);
tasksCompleted = hello;
tasksCorrect = 0;
userType = Student;
username = clinhart;
}]
Not sure if anyone has more knowledge of the parse api, mainly how the saveall/saveallinbackground functions work maybe.
To save all in background as a user I would first create a PFUser variable, like
var NewUser = PFUser.currentUser
Then to save in background
newUser.saveInBackgroundWithBlock {
(success:Bool, error: NSError!) -> Void in {
}
Then you can put if-statements and stuff within those brackets to do what you need it to when successful. like:
if(success) {
performSegueWithIdentifier("YourSegue", sender: nil)
}