I need to write an app that takes the string that is entered into a text field and use it to call a thesaurus function. The function must return an array that contains synonyms to the string, but I seem to be having some syntax issues. Can someone lend an extra pair of eyes?
I already checked on the syntax and the scope of the variables, but I don't seem to understand where I'm getting it wrong.
var synonymsDictionary = ["swift" : ["abrupt", "expeditious", "hasty", "nimble", "quick", "rapid", "speedy", "sudden", "unexpected"],
"objective" : ["detached", "disinterested", "dispassionate", "equitable", "evenhanded", "nonpartisan", "open-minded", "unbiased"],
"calculate" : ["adjust", "appraise", "consider", "count", "determine", "forecast", "gauge", "guess", "measure", "multiply", "reckon", "subtract", "tally", "weigh", "work out"],
"create" : ["build", "conceive", "constitute", "construct", "design", "devise", "discover", "establish", "forge", "form"]]
func synonyms(for term: String) -> String {
if let sameWords = synonymsDictionary[term] {
print("These are the synonyms for \(term): \(sameWords)")
} else {
print("This word doesn't have any synonyms.")
}
let result = synonymsDictionary[term]
return result
}
synonyms(for: "objective")
I should be getting an array with the synonyms for the term (string ) that I put in.Error
Cannot convert return expression of type '[String]?' to return type 'String'
Currently you return String but it should be an array [String] so try
func synonyms(for term: String) -> [String] {
return synonymsDictionary[term] ?? []
}
Also hold a reference to the returned value
let res = synonyms(for: "objective")
print(res)
Since synonymsDictionary is a dictionary [String:[String]] then every value is of type [String] that can't be returned in a function that returns a value of type String
Related
struct Test {
var title: String
var message: [String?: String?]
init(title: String, message: [String?:String?]) {
self.title = title
self.message = message
}
}
var cases = [
Test(title: "1", message: ["tag1": nil]),
Test(title: "2", message: ["tag2": "preview2"]),
Test(title: "3", message: [nil:nil]),
Test(title: "4", message: ["tag1":"preview4"])
]
Now, I want:
An array with all keys from message property from cases - tag1 and tag2 (no nils in it). I just tried everything I know, I couldn't do it. Tried with filtering cases, got optionals.
There are no previews without a tag, so there is no need for an array with them. I only need a list with the tags, in order to sort it and show the relevant previews from the cases. That's why I need to know a way how to access these previews from the cases. Let's say in a UITableView:
cell.previewLabel?.text = cases[indexPath.row].preview[//No idea what here]
Of course, a dictionary with [tags: previews] would also be perfect!
Thanks in advance! I hope what I want is possible.
Here is an array that only contains elements from cases that have all keys and values not nil :
let filtered = cases.filter { test in
return test.message.allSatisfy({ entry in
return entry.key != nil && entry.value != nil
})
}
Or using the shorthand notation :
let filtered = cases.filter {
$0.message.allSatisfy({
$0.key != nil && $0.value != nil
})
}
With structs there is a default initializer, so you can write your Test struct this way:
struct Test {
var title: String
var message: [String?: String?]
}
It's not completely clear to me what you're attempting to do, however, this will filter your cases array to only Test objects that contain non-nil values in the message dictionary:
let nonNil = cases.filter { (test) -> Bool in
return Array(test.message.values).filter({ (value) -> Bool in
return value == nil
}).count <= 0
}
The variable nonNil now contains the Test objects where title is "2" and title is "4".
You could further filter that if you want a [tags:preview] dictionary. Something like this would do that:
let tags = nonNil.map( { $0.message} ).flatMap { $0 }.reduce([String:String]()) { (accumulator, current) -> [String:String] in
guard let key = current.key, let value = current.value else { return accumulator }
var accum = accumulator
accum.updateValue(value, forKey: key)
return accum
}
The tags dictionary now contains: ["tag1": "preview4", "tag2": "preview2"]
I have code like this:
class Stack<T>: CustomStringConvertible {
fileprivate var array: [T] = []
func pop() -> T? {
let popItem = self.array.popLast()
print("POP ITEM : \(popItem)")
return popItem
}
func push(item: T) {
print("PUSH ITEM : \(item)")
array.append(item)
}
var isEmpty: Bool {
return self.array.isEmpty
}
var count: Int {
return self.array.count
}
var description: String {
let topDivider = "### STACK ###\n"
let bottomDivider = "\n############\n"
let stackElements = self.array.reversed().joined(separator: "\n") // GETTING ERROR
return topDivider + stackElements + bottomDivider
}
}
Error: Type of expression is ambiguous without more context
I'm unable to join that reverse array.
REF : https://www.raywenderlich.com/149213/swift-algorithm-club-swift-stack-data-structure
Here they have done in struct with String successfully.
Can i know How i can achieve same here?
The problem is that the joined function requires that the separator be the same data type as the values being joined. Since self.array is an array of T, you can't pass a String as the separator. This mismatch is causing the error.
Since this is your description property and your goal is to get a string representation of the array, one solution would be to map the array of T to an array of String. Then you can join that String array with your newline separator.
One way to convert something to a String is to call the description method on it. But to do that, you need to limit your T to only those types that provide the description method which comes from CustomStringConvertible.
Change your class declaration to:
class Stack<T:CustomStringConvertible>: CustomStringConvertible {
and then your description property to:
var description: String {
let topDivider = "### STACK ###\n"
let bottomDivider = "\n############\n"
let stackElements = self.array.reversed().map { $0.description }.joined(separator: "\n")
return topDivider + stackElements + bottomDivider
}
Map your generic type T to String and then apply joined() function.
joined is only for elements of type String and here compiler do not know the type of T.
let stackElements = self.array.map{"\($0)"}.reversed().joined(separator: "\n")
I'm trying to take two arrays and combine them into a new array without any duplicates. I can't get around the following error, however.
Cannot convert value of type '(Any) throws -> Bool? to expected argument type '(Any) throws -> Bool?
I'm trying to combine two arrays which contain multiple dictionaries. I'm comparing the "name" in each dictionary in the array.
let array2Name = array2.flatMap({$0["name"]}) // ["eli", "will"]
array2 = array1.reduce(array2) { !array2Name.contains(where: $1["name"] as! (Any) throws -> Bool? ?? "") ? $0 + [$1] : $0 }
print(array2)
You aren't properly comparing the value that is passed into the contains closure. And you can't use the $ variable inside a closure within the closure.
let array2Name = array2.flatMap { $0["name"] }
array2 = array1.reduce(array2, { result, value in
!array2Name.contains(where: { $0 == value["name"] ?? "" }) ? result + [value]: result
})
print(array2)
Edit:
This does away with the array2Name value.
array2 = array1.reduce(array2) { result, value in
result.contains(where: { $0["name"] == value["name"] }) ? result: result + [value]
}
I am developing search textfield. I have an array of Strings that looks like this....
var keywords:[String] = ["dance, music and hippo", "apple juice, tomato"]
I tried to use function contains but its not doing well.
for i in 0..<keywordsArr.count {
if(!keywordsArr[i].contains(searchTextField.text!)){
print("removed \(keywordsArr[i])")
keywordsArr.removeAtIndex(i)
}
}
this is extension that i am using.
extension String {
func contains(find: String) -> Bool{
return self.rangeOfString(find) != nil
}
}
the result should be i am calling function with text: "music" and it should return index of that string
You can achieve this very succinctly, using filter, which returns an array with only elements for which the closure holds. You should also use optional binding to avoid using a force unwrap of searchTextField.text
if let text = searchTextField.text {
keywordsArr = keywordsArr.filter { $0.contains(text) }
}
First you shouldn't edit the array size inside the loop, because each time you iterate you recalculate its size with "keywordsArr.count", and that will cause an exception You can use those few lines to return the index of the string if it's contained in your array, or -1 if not. good luck
func doesContain(array:[String], searchString:String) -> Int {
let size = array.count
for i in 0..<size {
if array[i].rangeOfString(searchString) != nil {
print("exists")
print("removed \(array[i])")
return i
}
}
return -1
}
var keywords:[String] = ["dance, music and hippo", "apple juice, tomato"]
doesContain(keywords, searchString: "music")
I have an array with data for my TableView sections
let menuItems : Dictionary<String,Dictionary<String,String>>[] = [
[
"data" : [
"name":"test",
"image":"test.png"
]
],
[
"data" : [
"name":"test2",
"image":"test2.png"
]
]
]
I'm trying to access it by using subscript
func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! {
return menuItems[section]["data"]["name"]
}
and have the error
Could not find member 'subscript'
I have read a lot of similar questions on stackoverflow, but still haven't understood how to fix it. I tried to unwrap with "!" symbol and used another variables - no result.
Could you explain how does it works, please?
println(menuItems[0]["data"]!["name"])
Short answer: menuItems[0]["data"] returns an optional dictionary.
You can look at the below REPL output to understand the issue.
sets up the object.
shows that the array returns a regular dictionary. If the index is out of range, an error will be thrown instead of returning an optional dictionary.
shows that accessing a key in a dictionary that does not exist will return nil
shows that accessing a key in a dictionary will return an optional of its value type. For instance, if a dictionary is storing Strings in its values, it will return a String? when indexed into.
shows that we cannot use subscripts on an optional dictionary.
shows that we can force the optional dictionary to be a dictionary because we know it is not nil. The REPL shows us that the new return type is Dictionary<String, String>
shows that we can then use subscripts to get at the innermost values, and this returns an optional string to us. Optional strings are printable, so my code above doesn't need a second !.
shows that if we force both dictionary return types to their non-optional types, we get a regular value back (a string).
In real code, you would probably want to check for optionals, and handle nils accordingly.
1> let menu: Dictionary<String, Dictionary<String, String>>[] = [["dict1" : ["key" : "val"]], ["dict2" : ["key" : "val"]]]
menu: Dictionary<String, Dictionary<String, String>>[] = size=2 {
[0] = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
[1] = {
[0] = {
key = "dict2"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
}
2> menu[0]
$R1: Dictionary<String, Dictionary<String, String>> = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
3> menu[0]["key"]
$R2: Dictionary<String, String>? = nil
4> menu[0]["dict1"]
$R3: Dictionary<String, String>? = Some {
[0] = {
key = "key"
value = "val"
}
}
5> menu[0]["dict1"]["key"]
REPL:6:1: error: could not find member 'subscript'
menu[0]["dict1"]["key"]
^~~~~~~~~~~~~~~~~~~~~~~
6> menu[0]["dict1"]!
$R4: Dictionary<String, String> = {
[0] = {
key = "key"
value = "val"
}
}
7> menu[0]["dict1"]!["key"]
$R5: String? = "val"
8> menu[0]["dict1"]!["key"]!
$R6: String = "val"