1

Curious to know if anyone has a swift closure solution to transform the following for/in loop iteration over an array containing multiple class objects? The class is composed of two properties of type string. A class function instantiates multiple objects and places them into an array. In the example below, the array nhSearchObject has 10 indices containing 10 objects of the class.

class President{
   var firstName:String 
   var lastName:String
    init(...)
    }       
  // class function creates objects and places them into an array   nhSearchObject

for i in nhSearchObject[0...6] {
    i.firstName = "George"
    i.lastName = "Washington"
}

It is imperative to preserve the subscript range feature as I only want to change the indices 0...6. Also, I do not want to create a new array. Simply interested in iterating over the array slice 0..6 of the 10 indices of the existing array to modify object properties.

P.Festus
  • 95
  • 2
  • 11
  • 1
    What's wrong with the `for in` loop? It's both clear and concise. – Hamish Jan 27 '17 at 15:05
  • 1
    *has 10 elements containing 11 objects of the class.* how's that possible? – mfaani Jan 27 '17 at 15:14
  • There is nothing wrong with it. I am learning closures and can't figure out how to use a closure to iterate over an array using an array slice. – P.Festus Jan 27 '17 at 15:15
  • @Honey the first element is 0 so there are 11 objects in the array – P.Festus Jan 27 '17 at 15:15
  • 1
    I'm not sure if I understand you. e.g. `let arr = [1,5,4]`. <-- has 3 indexes and 3 values inside. arr[0] is 1, arr[1] is 5, arr[2] is 4 – mfaani Jan 27 '17 at 15:17
  • @Honey I'm not sure if it really matters how one might count the objects for purposes of answering the question. However, yes, I see your point. 3 indices has three objects inside. For the sake of clarity I edited the text. – P.Festus Jan 27 '17 at 15:22
  • 1
    `nhSearchObject[0...6].forEach { ... }` or `nhSearchObject.prefix(7).forEach { ... }` ? – Martin R Jan 27 '17 at 15:27
  • @MartinR. Thx. I'll give it a try. – P.Festus Jan 27 '17 at 15:31
  • @MartinR This is embarrassing. I'm following the same logic, but can't get it to work. `var x = [1,2,3]; var m = x[0...2].forEach{$0*5};print(x)// [1,2,3];print(m) // ()`. `m` only prints to`()`. – mfaani Jan 27 '17 at 15:50
  • 1
    @Honey: You are confusing two things. A class is a *reference type,* therefore you can modify the properties of the (referenced) array elements in `nhSearchObject[0...6].forEach { $0.firstName = "George" }`. An array is a struct and a *value type,* where you cannot do that. Also `forEach` does not *return* anything. `let m = x[0...2].map { $0 * 5 }` would create a new array, but that is different from what you originally asked. – Martin R Jan 27 '17 at 15:55
  • @MartinR Thanks (I'm not the OP). I *somewhat* see what you are saying. *An array is a struct and a value type, where you cannot do that*. so how come I do `x.sort()` and it sorts ie modifying itself. – mfaani Jan 27 '17 at 16:14
  • @Honey: sort() rearranges the array elements, it does not modify the properties of its elements. What I meant is: In your example `x[0...2].forEach{$0*5}` the `$0` is a *value* and a "copy" of an element in `x`. In `nhSearchObject[0...6].forEach { $0.firstName = "George" }` the `$0` is a *reference* to an object. – Martin R Jan 27 '17 at 16:19
  • @MartinR - it worked! Thx. – P.Festus Jan 27 '17 at 19:01
  • @honey, the answer of your question lies [here](http://stackoverflow.com/questions/26371751/changing-the-value-of-struct-in-an-array) – mfaani Jan 27 '17 at 20:41

2 Answers2

2

First of all your class is President (no Presidents)

class President {
    var firstName:String
    var lastName:String
    init(firstName: String, lastName:String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

Now given the following array

let presidents: [President] = ...

you can follow 2 approaches

If you are sure the array has at least 7 elements then

presidents[0...6].forEach { president in
    president.firstName = "George"
    president.lastName = "Washington"
}

Otherwise

presidents
    .enumerated()
    .filter { $0.offset <= 6 }
    .forEach { elm in
        elm.element.firstName = "George"
        elm.element.lastName = "Washington"
    }
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • 1
    At first I thought to myself: I can name a class whatever I want. However, I agree that the proper name for the class would be President in the singular given that one creates multiple objects of the class. Thank you for the correction. – P.Festus Jan 27 '17 at 15:43
  • 1
    I think you meant `$0.offset < 6`, however, you probably want to use `prefix(6)` instead of `enumerated` and `filter`. – Sulthan Jan 27 '17 at 16:00
  • AppzYourLife - Thank you for the code solutions. I believe that your code, consistent with that of @MartinR's solution noted in the above comments, are correct. – P.Festus Jan 27 '17 at 19:09
-1

nhSearchObject.forEach { $0.firstName = "George"; $0.lastName = "Washington" }

  • How does the closure apply to elements 0...6 of 10 array elements? the solution proposed would apply to all 10 elements of the nhSearchObject. – P.Festus Jan 27 '17 at 15:09