im new to swift.I tried to follow many tutorials but still im not able to find a solution for it.
I want to pass values stored in an array to a function.
let trackList = ["AC","BB"]
for trackId in trackList{
let ind = trackList.index(of: trackId)
let index = trackList.startIndex.distance(to: ind!)
let num = Int(String(describing: ind))
let track = String(trackId)
addDiaryList(track:String) //i keep getting error here saying: Cannot convert value of type 'String.Type' to expected argument type 'String'
}
func addDiaryList(track:String) {
}
That's easy, the function call is wrong. It should be
addDiaryList(track:track!)
The first track stands for the parameter name in the function, the second one for the variable you assigned two rows above.
But I think you're doing a lot of useless calls here, it could rather be:
let trackList = ["AC","BB"]
func addDiaryList(track:String) {
}
for trackId in trackList{
addDiaryList(track: trackId)
}
Related
let mut args: Vec<String> = args().collect();
for mut i in 0..args.len() {
if args[i].contains("-type") {
project_type = args[i].split("=").last().unwrap();
args.remove(i);
i-=1;
}
}
I'm very new to rust and want to know why this code gives me the error "cannot borrow 'args' as mutable because it is also borrowed as immutable" and how i can fix it
I'm trying to check if the args Vec contains an item like "-type=some_type", then put "some_type" in a variable called "project_type". Finally I want to remove the item "-type=some_type" from the list and keep searching.
edit: if I'm doing what I'm trying to do wrong, i would appreciate a better solution.
str::split doesn't create new string objects, it returns references to the existing one. So your project_type variable is a reference to a string in args. When you remove from args, you invalidate all of those references.
You can convert a &str to a String and break the reference with .to_owned()
project_type = args[i].split("=").last().unwrap().to_owned();
Now, for loops in Rust iterate over data structures. As such, your i -= 1 trick won't work. i will just get reset back to where it was at the next iteration. If you want to do this the way you're currently doing it, you want a while loop.
let mut i = 0
while i < args.len() {
if ... {
...
} else {
i += 1;
}
}
However, let's think about this a bit more functionally. What it sounds like you want is to find a matching element of a vector (and its index) and then do something with it. So let's break that down into two separate problems.
We use enumerate to get a collection together with its index, and find to search it. Since it looks like you expect the value to be there, we'll unwrap it and panic if it's not there. If you want to handle the error, convert this to a match.
let (idx, element) = args.iter().find(|x| x.contains("-type")).unwrap();
Once we have it, we can do our work on element to get the project type.
project_type = element.split("=").last().unwrap().to_owned();
Note that at this point project_type does not depend on args at all. element does, and Rust may be smart enough to see this, but let's just be perfectly safe and make sure element gets dropped before we modify args. Once there are no more references to args, we can mutably borrow to do the remove operation.
let idx = {
let (idx, element) = args.iter().enumerate().find(|(_, x)| x.contains("-type")).unwrap();
project_type = element.split("=").last().unwrap().to_owned();
idx
}
args.remove(idx);
Why there aren't any compilation errors in this code?
Code:
function partial(f: (a: string) => string, a: string) : string {
return "";
}
var test = () => "";
var result = partial(test, "");
Function "partial" takes as the first argument a function, that takes one parameter, but I pass to it function, that doesn't take any parameters, and typescript compiler thinks, that this is OK. I understand that this can't break anything because you can pass all parameters in the world to the function that doesn't take any, and it won't break anything, but it should be a compilation error because typescript is about types and there is an obvious type missmatch and it can possible be a developer's error.
Is there any workarounds for this problem?
there is an obvious type missmatch and it can possible be a developer's error.
There's nothing obviously wrong with this code. Consider something like this:
let items = [1, 2, 3];
// Print each item in the array
items.forEach(item => console.log(item));
Is this code correct? Definitely! But forEach invokes its provided function with three arguments, not one. It would be tedious to have to write:
items.forEach((item, unused1, unused2) => console.log(item));
Note that you can still get errors if you try to do something that's actually wrong. For example:
function printNumber(x: number) { console.log(x); }
let strings = ['hello', 'world'];
strings.forEach(printNumber); // Error, can't convert string to number
I have an array of object, each object contains a discount rate , I need to sort them increasingly by their rate,
struct ShopDetails {
var shopId: Int?
var discountRate: String?
init(with json: Dictionary<String,Any>) {
shopId = json["id"] as? Int
discountRate = json["discount"] as? String
}
I tired to sort them using this method;
func getShopsByDiscount() {
let sortedImages = self.copyOfShops.sorted(by: { (shop1: ShopDetails, shop2: ShopDetails) -> Bool in
return Int(shop1.discountRate) < Int(shop2.discountRate)
})
}
I tried to cast the rate to integer, since its been received form the backend as string, but I got an error:
value of type Any has no member discountRate.
any idea how to do it? if there is a way to do it without casting it will be better
First, you need to verify that the array you're starting with is of type [ShopDetails]. The error indicates that this is probably an Objective-C NSArray, which won't work as well in Swift. If you're unclear about this, I suggest you Google the topic: there's no reason to use NSArray in Swift.
Below, I assume the array is the correct type ([ShopDetails]). From here, you need to do two additional things, because discountRate is of type String?.
You need to check if the string is actually there
You need to check if it can actually be expressed as an Int.
With these things in mind, your sort function can look like this:
let sortedImages = copyOfShops.sorted(by: {
(shop1: ShopDetails, shop2: ShopDetails) -> Bool in
if let shop1String = shop1.discountRate, let shop1Value = Int(shop1String),
let shop2String = shop2.discountRate, let shop2Value = Int(shop2String) {
return shop1Value < shop2Value
}
return true
})
That being said, the best way to handle this is to change the type of discountRate from String? to Int, and do the above checks when you init(with json: Dictionary<String,Any>). If the server giving you the dictionary is something you control, have it switch to passing back Ints instead of Strings, and stop dealing with optionals if you don't have to.
I'm trying to create a function that will take in one argument as a string, and delete that string from an array. I've looked and tried 'remove(at:)' but this is not working. I need the function to take in the droid's name, and delete it from the array. It's so simple, but I can't find anything anywhere that would help. I keep finding things that specify a certain place in the array as an Int, but I need the function to work with a string.
var starWarsDroids: [String] = ["R2-D2", "C-3P0", "IG-88", "BB-8"]
func removeDroid(droid:String) {
starWarsDroids.remove(at:0)
}
removeDroid(droid: "C-3P0")
print(starWarsDroids)
This is all I could come up with, and I know it doesn't work, so please don't tell me it doesn't. There has to be a way to do this without specifying a place in the array with an Int.
This should work.
var starWarsDroids: [String] = ["R2-D2", "C-3P0", "IG-88", "BB-8"]
func removeDroid(droid:String) -> Bool {
if let index = starWarsDroids.index(of: droid) {
starWarsDroids.remove(at: index)
return true
}
return false
}
func removeDroid(droid: String) {
starWarsDroids = starWarsDroids.filter{$0 != droid}
}
import Foundation
func insertionSort<T where T: Comparable>(var items:[T])-> [T] {
for (index, _) in items.enumerate().dropFirst() {
var j = index
while ((j > 0) && (items[j] < items[j-1])) {
swap(&items[j], &items[j-1])
j = j-1
}
}
return items
}
// Test the function
insertionSort([]) // Generic type array is not taking empty array
When I am trying to call insertionSort with empty array, I get
Cannot invoke 'insertionSort' with an argument list of type '([_])'
I am not able to figure out how to fix this.
To call generic functions in Swift, Swift needs to be able to infer the generic parameters.
One way giving the type information to Swift, is using an intermediate variable.
(Like noted in Lu_'s comment.)
let arr: [Int] = []
let result = insertionSort(arr)
Another way is using as.
let result = insertionSort([] as [Int])
(Remember, var parameter does not modify the actual argument. It just makes a mutable copy, but does not write it back to the original argument. Swift 3 removed var parameters, as it's so confusing. You may need to assign the return value of the function to a variable.)