如何更改数组中struct的值?

时间:2017-01-15 19:53:59

标签: arrays swift struct

我使用swift作为我的项目。

我有一个名为 $scope.delete = function(thing) { $http.delete('/api/drugs/' + thing._id).success(function(){ $scope.alldrugs = $scope.alldrugs.filter(function(t) { return t._id !== thing._id; // Remove the drug which was deleted }); }) .error(function() { // Drug couldnt be deleted, notify the user? }); }; 的结构数组。后来我创建了一个从数组中返回特定Instrument的函数。然后我想在其中一个属性上更改值,但此更改不会反映在数组中。

我需要让这个数组包含内部元素的所有更改。您认为这里的最佳做法是什么?

  • InstrumentInstrument更改为struct
  • 以某种方式重写从数组返回class的函数。

现在我使用这个功能:

Instrument

我从结构开始,因为已知swift是结构语言,我想知道何时使用func instrument(for identifier: String) -> Instrument? { if let instrument = instruments.filter({ $0.identifier == identifier }).first { return instrument } return nil } 的{​​{1}}。

感谢

2 个答案:

答案 0 :(得分:12)

使用struct Instrument数组,您可以获取具有特定标识符的Instrument的索引,并使用它来访问和修改Instrument的属性。

struct Instrument {
    let identifier: String
    var value: Int
}

var instruments = [
    Instrument(identifier: "alpha", value: 3),
    Instrument(identifier: "beta", value: 9),
]

if let index = instruments.index(where: { $0.identifier == "alpha" }) {
    instruments[index].value *= 2
}

print(instruments) // [Instrument(identifier: "alpha", value: 6), Instrument(identifier: "beta", value: 9)]

答案 1 :(得分:1)

如果您坚持使用值类型方法(并且假设identifier不是唯一的:否则,考虑使用字典进行简单的提取和替换逻辑),您可以将变异函数写入该类型拥有[Instruments]数组,该数组在数组中找到(第一个)Instrument实例,并使用提供的闭包对其进行变异。例如。 (感谢@Hamish的改进!):

struct Instrument {
    let identifier: String
    var changeThis: Int
    init(_ identifier: String, _ changeThis: Int) {
        self.identifier = identifier
        self.changeThis = changeThis
    }
}

struct Foo {
    var instruments: [Instrument]

    @discardableResult // do not necessarily make use of the return result (no warning if not)
    mutating func updateInstrument(forFirst identifier: String,
            using mutate: (inout Instrument) -> ()) -> Bool {
        if let idx = instruments.indices
            .first(where: { instruments[$0].identifier == identifier }) {

            // mutate this instrument (in-place) using supplied closure
            mutate(&instruments[idx])

            return true // replacement successful
        }
        return false // didn't find such an instrument
    }
}

使用示例:

var foo = Foo(instruments:
    [Instrument("a", 1), Instrument("b", 2),
     Instrument("c", 3), Instrument("b", 4)])

// make use of result of call
if foo.updateInstrument(forFirst: "b", using: { $0.changeThis = 42 }) {
    print("Successfully mutated an instrument")
} // Successfully mutated an instrument

// just attempt mutate and discard the result
foo.updateInstrument(forFirst: "c", using: { $0.changeThis = 99 })

print(foo.instruments)
/* [Instrument(identifier: "a", changeThis: 1), 
    Instrument(identifier: "b", changeThis: 42), 
    Instrument(identifier: "c", changeThis: 99),
    Instrument(identifier: "b", changeThis: 4)] */

@Owen:s answer所示,找到元素上某个谓词的第一个索引的更简洁的方法是使用index(where:)数组方法(而不是上面使用的indices.first(where:) )。在上面的完整示例中使用index(where:)方法将简单地对应于替换

if let idx = instruments.indices
    .first(where: { instruments[$0].identifier == identifier }) { ...

if let idx = instruments
    .index(where: { $0.identifier == identifier }) { ...
updateInstrument(forFirst:using) Foo方法中的

我们可以通过应用updateInstrument(forFirst:using)的{​​{1}}函数来进一步压缩map方法,以便在一行中执行(可能的)替换和布尔返回:

Optional