15 Replies
Latest reply on Mar 24, 2020 4:51 PM by G.U.T.explorer
Level 1 (0 points)

This comes up a lot (for years) and has me buggered.

1. class Act: Codable {
2.    var a:  Uint32
3.    var b: [UInt32]?
4. .
5. .
6. .
7.    var z: [UInt32]?
8.    init( ...vars...)
9. }

I want to do a simple sum on .nonzerobitCount for every var a through z.

I can write code to check,e.g.,

10. if Act.b != nil {for index in 0..<Act.b!.count { if Act.b?[index] != nil { totalBits += Act.b?[index].nonzeroBiCount } } }

but even with copy and paste this is exhausting and cludgy.

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)

All var are arrays, except a. Is it on purpose ?

I want to do a simple sum on .nonzerobitCount for every var a through z.

What do you want to count exactly

Is it ?

```        var totalBits = 0
if b != nil {
for index in 0 ..< b!.count {
if b?[index] != nil {
totalBits += b?[index].nonzeroBitCount
}
}
}
if c != nil {
for index in 0 ..< c!.count {
if c?[index] != nil {
totalBits += c?[index].nonzeroBitCount
}
}
}
// repeat until z```

line 04:

- b is not nil so b? is useless, use b!

- how could b![index] be nil ?

line 05:

I would do the following

```        var totalBits = 0
var b: [UInt32]?
var c: [UInt32]?
var d: [UInt32]?
var z: [UInt32]?
var bToz : [[UInt32]?] = [b, c, d, z]     // You have to type all var names

for xx in bToz {
if xx != nil {
for index in 0 ..< xx!.count {
totalBits += xx![index].nonzeroBitCount
}
}
}```

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)

Some refinement to simplify:

```       for xx in bToz {
if xx != nil {
for item in  xx! {
totalBits += item.nonzeroBitCount
}
}
}```

or

```for xx in bToz where xx != nil {
totalBits += xx!.reduce(0) { \$0 + \$1.nonzeroBitCount }
}```
• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

I have rechecked my code, you are right about line 04 being useless, b[index] cannot be nil because it was included in the Act.b!.count.

Thanks!

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

I took a closer look at your line 06

" var bToz : [[UInt32]?] = [b, c, d, z]     // You have to type all var names "

If I make Act.a:[UInt32], even though it would hold just one UInt32, a var aToz could be added within the class declaration:

var aToz: [[UInt32]?] { return [ a, b, c, d...., z] }

The beauty of which is that it needs no initializer, so my init's throughout the code are not affected.  All I had to do was put brackets, [ ], around every existing reference to Act.a     Not as painful as I thought it might be.

Thanks for the inspiration!

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

Just to be clear, I can now code a for-loop to go through just-the-vars-I-want:

1. class Act: Codable {
2.    var a: [Uint32]
3.    var b: [UInt32]?
4. ...
5.   var z: [UInt32]?
6.   var aToz: [[UInt32]?] { return [ a, b, c, d...., z] }
7.    init( ...vars...)
8. }

...

100.     for member in Act.aToz { if member != nil {for index in 0..<member!.count { totalBits += member?[index].nonzeroBitCount } } }

A further benefit is that when my "class Act" is written to a JSON file, the computed var "aToz" is not in it, not even a mention of it.  So the file size is not "doubled" by adding the computed var!  Love it.

I want to rework : "let totalBits = act.b?.reduce(0, {\$0 + \$1.nonzeroBitCount}) ?? 0" and use it eventually... it's beautiful!

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)

If I make Act.a:[UInt32],

That was my very first question: quote 'All var are arrays, except a. Is it on purpose ?'

So, is it solved ?

If so, don't forget to close the thread by marking the 'inspiration' answer.

Good continuation.

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

New here.  What's the "inspiration" answer?

I hope you got a point for my clicking "This helped me" but I don't know if you did.

• ###### Re: how to loop through array(s) of optionals
Level 8 (6,095 points)

First of all, you should better re-consider if you really need Optional Arrays.

But that's another issue and you may need it in some cases.

If I were given an Optional Array, I would write something like this:

```    var totalBits: Int = 0
for element in act.b ?? [] {
totalBits += element.nonzeroBitCount
}

```

Or, you can write it in a single line if you are familiar with `reduce`:

```    let totalBits = act.b?.reduce(0, {\$0 + \$1.nonzeroBitCount}) ?? 0

```

When multiple Optional Arrays given, this would work:

```    let totalBits = [act.b ?? [], /* ...,*/ act.z ?? []].joined().reduce(0, {\$0 + \$1.nonzeroBitCount})

```
• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

in order of response:

to Claude31:

• line 04:
- b is not nil so b? is useless, use b!
- how could b![index] be nil ?

It might be that not all b are occupied, e.g., just the first in the array.  My fault for not specifying every detail: towit, e.g., b can have up to four members in the array, or none.

• line 05:

Sorry, yes a typo.  This is not copied directly from my code but constructed just for this inquiry.

to OOper:

Yeah... I can't think of another way to "not use optional arrays".

I love seeing your mystical syntax code.  I'll try it.  I'm not fluent with closures.  I've used them of course, but still find them mystical.

to all:

I have failed in my request.

I am looking for a way to "for loop" through Act's vars [a, b, c, ...,z] so I can apply any of the above methods.

I have tried in vain to use enum.

I have also considered making the vars a...z another level in the array so that the class Act has just one var, call it alpha then I could:

for mychar in alpha{ insert line 10 here }

But this would be a major rewrite of my app.  I thought there might be a better way to loop through the members of the class.

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)
• line 04:
- b is not nil so b? is useless, use b!
- how could b![index] be nil ?

It might be that not all b are occupied, e.g., just the first in the array.  My fault for not specifying every detail: towit, e.g., b can have up to four members in the array, or none.

b is an optional array (not an array of optionals.

So if b is not nil, b![index] cannot be nil ; it can crash for out of bounds index, but not be nil.

I tested the exact following code in playground, to loop through all vars (from b to z)

I renamed vars as bB, cC… because I already used b, c…:

```var totalBits = 0
var bB: [UInt32]?
var cC: [UInt32]? = [125]
var dD: [UInt32]?
var zZ: [UInt32]? = [4123]
var bToz : [[UInt32]?] = [bB, cC, dD, zZ]     // You have to type all var names

for xx in bToz {
if xx != nil {
for index in 0 ..< xx!.count {
totalBits += xx![index].nonzeroBitCount
}
}
}
print(totalBits)
totalBits = 0
for xx in bToz {
if xx != nil {
for item in  xx! {
totalBits += item.nonzeroBitCount
}
}
}
print(totalBits)
totalBits = 0
for xx in bToz where xx != nil {
totalBits += xx!.reduce(0) { \$0 + \$1.nonzeroBitCount }
}
print(totalBits)```

I get the following correct results:

11

11

11

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

"b is an optional array (not an array of optionals."

UhOh.  You're right again.  I have to rethink this. The array Act.a must exist and be non-nil, but all other vars Act.b thru z need not have values.  Nor arrays then?  Might I need optional arrays of optionals?  Now I feel like I stepped in something.  :-(

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)

You need to be very clear on what you get in var a to z.

Where are those UInt coming from ?

Optional are useful if you need to have a value:

- for instance, if each var was to contain exactly 6 items, you could declare the arrays as [UInt32?]

- but in that case, the array itself doesn't need to be optional

In your case, I understand you will have a variable number of items in arrays:

- a will have one,

- b may have 6

- c may have 0.

But all var a, b, c exist.

So, no need to be optional, but just declare initially as empty (hence no init needed):

var a : [UInt32] = []. // or var a = [UInt32]()

With this, your code becomes (tested in playground):

```var totalBits = 0
var a: [UInt32] = []
var b: [UInt32] = []
var c: [UInt32] = []
var d: [UInt32] = []
var z: [UInt32] = []
var aToz : [[UInt32]] = []     // You have to type all var names

func computeTotal() -> Int {
var total = 0
for xx in aToz {
total += xx.reduce(0) { \$0 + \$1.nonzeroBitCount }
}
}

// Somewhere, you will populate the arrays (getting a JSON Request, typing by user, … whatever way ; here I set manually)
func populateVar() {
a = [100]
b = [50, 200]
c = [125, 6, 314]
d = []
z = [4123]
aToz = [a, b, c, d, z]     // You have to type all var names

totalBits = computeTotal()
print(totalBits)
}

populateVar()```

I get the result in log:

27

As a conclusion

It is better here to have the same type for all, even to hold a single value or no value.

Globally, you should avoid adding optional everywhere

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

I tried using optional arrays of optionals.  It just made my code messy.  It was easier to deal with a formed array that had a zero value than add a couple hundred "!" to optionals calls.

btw: the code "var aToz : [[UInt32]] = []" may work outside a class declaration, as in a playground, but fails within one.

"     var aToz: [[UInt32]?] { return [ a, b, c, d...., z] }     " works inside a class.  You lead me to that and I am thankful.  My code works now.

• ###### Re: how to loop through array(s) of optionals
Level 8 (9,135 points)

• I tried using optional arrays of optionals.  It just made my code messy.  It was easier to deal with a formed array that had a zero value than add a couple hundred "!" to optionals calls.

I just proposed to REMOVE optionals

• btw: the code "var aToz : [[UInt32]] = []" may work outside a class declaration, as in a playground, but fails within one.

I just tested 1 minute ago, in a class or inside a func, it works perfectly OK of course.

But you need to initialize its content somewhere.

What is the error you get to understand the error you made ?

Anyway, it is good to know it works, don't forget to close the thread.

• ###### Re: how to loop through array(s) of optionals
Level 1 (0 points)

I stand corrected.  I just copied and pasted "var aToz : [[UInt32]] = []" into my class and it was accepted this time.  Don't know what i did the first time.

As for the optionals: my actual code creates UInt32=zero for a finite number of members of any array that has at least one real value.  So if a given array has just one real value the other members get zero, and it is easier to if=zero than to optionalize (to nil)... you know what I mean, and then if!=nil.  Maybe that's as clear as mud but without showing the actual code it would take too much explaining.

As for "initializing the  content" of the aToz, thats what "var aToz: [[UInt32]?] { return [a, b, c, ... z] } " does.  That is to say, the closure does the initialization, as I understand it.

My happy results are found @: G.U.T.explorerMar 24, 2020 9:42 AM