0

I have 2 question. First, I can't convert String array to Int array from core data

let sum = recordFilter.map{$0.amount!.dropFirst()} //["9.99", "6.58"]
let intSum = sum.map({Int($0)})  //[nil, nil]

My array format:

[<Record: 0x600000099fa0> (entity: Record; id: 0xd0000000003c0000 <x-coredata://913F25A5-B2C9-4646-9091-5EFE7F906908/Record/p15> ; data: {
    accountbook = "first book";
    amount = "\U00a59.99";
    assest = nil;
    category = "\U6295\U8d44";
    createdAt = "2017-11-16 16:00:00 +0000";
    date = nil;
    id = 15;
    recordtype = "\U6536\U5165";
    remark = "";
    toAccBook = nil;
}), ...})]

Second, I want to sum it by .reduce but I got Cannot invoke 'reduce' with an argument list of type '(Int, _)' How to fix it?

let sum = recordFilter.map{$0.amount!.dropFirst()}.reduce(0, +)
let intSum = sum.map({Int($0)}).reduce(0, +)
//Cannot invoke 'reduce' with an argument list of type '(Int, _)'
3
  • 1
    Int is integer without decimal places. The strings do have decimal places and even seem to start with a linefeed character in the record. Why do you use a string type for a numeric value anyway? Commented Nov 17, 2017 at 9:26
  • Oh thanks! I changed it to Float already, it works. how about the sum error? @vadian Commented Nov 17, 2017 at 9:35
  • You're apply reduce to string as int in first line. Just use it in second line not in first. Commented Nov 17, 2017 at 9:55

2 Answers 2

1

First, I can't convert String array to Int array from core data

From the description of init?(_ description: String)

The string passed as description may begin with a plus or minus sign character (+ or -), followed by one or more numeric digits (0-9)

9.99 is an invalid format for an Int which is probably why the map that tries to do the conversion is returning nil for each element.

If you do this:

let doubleSum = sum.map({Double($0)}) 

You'll get close to what you want but the elements of the array will be optionals.

Second, I want to sum it by .reduce but I got Cannot invoke 'reduce' with an argument list of type '(Int, _)'

The problem is that the constructor returns an optional. One way to fix this would be to unwrap the optionals but make nils zero for the purpose of the addition.

let doubleSum = sum.map{ Double($0) ?? 0.0 }.reduce(0, +)

you'll get what you want. The ?? unwraps the result of the string to double conversion, using 0 where the conversion fails.

Or, even better, as Martin R suggests, you can use flatMap to eliminate the need for ??.

let doubleSum = sum.flatMap{ Double($0) }.reduce(0, +)
Sign up to request clarification or add additional context in comments.

4 Comments

I found that it will get nil when the double value is above thousand. Is there any way to increase the limit? @JeremyP
@WanJern That sounds weird. Do your strings have separators every three digits?
@WanJern @Raphael has a point, if you have a value 1,234.00, the normal conversion routine will break because of the comma.
@WanJern in such a case, it's better to use a NumberFormatter to do the string conversion.
0

You should annotate explicit types for your variables to check if you are coding what you think you are. My guess is you are used to dynamic languages; it doesn't work that way here.

recordFilter.map { ... } creates a String, so reduce needs a pair of parameters of types T and (T, String) -> T, respectively. With T == Int, it's looking for +: (Int, String) -> Int which does not exist.

Note that if you fix that, sum is either String or Int (not sure what you want), to neither of which applying map does what you want it to do, by my estimation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.