Структура данных для последовательного массива в Swift - PullRequest
0 голосов
/ 02 января 2019

У меня есть два массива, которые используются последовательно.

var pinnedMessage: [Message]
var normalMessage: [Message]

Первый

Я добавляю закрепленные сообщения в первый массив, а обычные - во второй.я всегда использую оба массива последовательно.поэтому, когда я их использую, я создаю новый массив, сначала добавляю прикрепленные сообщения, а затем обычные сообщения.

var newArray: [Message] = []
newArray.append(pinnedMessage)
newArray.append(normalMessage)

Второй

Другой способ - поместить оба сообщения в один массив изатем сортируйте их по признаку их isPinned свойства.

GlobalArray.sort { $0.isPinned && !$1.isPinned }

Я также должен знать, где находится индекс первого нормального сообщения.поэтому у меня для этого тоже есть переменная.

Я не думаю, что эти идеи в порядке.Должен ли я использовать связанный список или другую структуру данных?

Ответы [ 3 ]

0 голосов
/ 02 января 2019

Вместо того, чтобы использовать любую из перечисленных вами альтернатив, вы можете вместо этого изменить способ доступа к своим массивам.Вы можете использовать вспомогательную функцию, принимая в качестве аргумента замыкание, для обработки каждого элемента в массивах:

struct Message {
    let text: String
}

let pinnedMessages: [Message] = [Message(text: "I'm pinned"), Message(text: "I'm also pinned")]
let normalMessages: [Message] = [Message(text: "I'm normal"), Message(text: "I'm also normal")]
@inline(__always)
func foreachMessage(function: (Message) throws -> ()) rethrows {
    try pinnedMessages.forEach(function)
    try normalMessages.forEach(function)
}

Если вам также необходимо знать тип сообщения, вам следует либо обработатьмассивы по отдельности, без вспомогательной функции, или пусть ваше закрытие принимает другой аргумент:

enum MessageType {
    case pinned
    case normal
}


@inline(__always)
func foreachMessage(function: (Message, MessageType) throws -> ()) rethrows {
    try pinnedMessages.forEach { try function($0, .pinned) }
    try normalMessages.forEach { try function($0, .normal) }
}
foreachMessage { message in
    print(message)
}

foreachMessage { message, type in
    print(message, type)
}

Использование такого метода освобождает вас от недостатка объединения двух массивов: памяти и накладных расходов на производительность.

Если вы отображаете эти сообщения, как если бы они были в одном массиве, индекс первого обычного сообщения будет просто после индекса последнего сообщения в массиве pinnedMessages.pinnedMessages.count будет равен последнему индексу этого массива + 1, равному первому индексу нормальных сообщений.

0 голосов
/ 02 января 2019

Вы можете создать один массив с добавленными как закрепленными, так и обычными сообщениями и использовать метод Swift 4.2 firstIndex(where:) для Collections, чтобы получить первый индекс нормального сообщения

struct Message {
    let isPinned: Bool
}

let pinned = [Message(isPinned: true), Message(isPinned: true), Message(isPinned: true)]
let normal = [Message(isPinned: false), Message(isPinned: false), Message(isPinned: false)]
let sortedArray = pinned + normal

if let firstIndex = sortedArray.firstIndex(where: { $0.isPinned == false }) {
    print(firstIndex)
}

если вы делаете это в UIViewController, то можете использовать didSet наблюдателя на sortedArray, чтобы установить firstIndex обычного сообщения

class ViewController: UIViewController {

    var normalPinFirstIndex: Int?

    var sortedArray: [Message] = [] {
       didSet {
            if !sortedArray.isEmpty {
                normalPinFirstIndex = sortedArray.firstIndex(where: { $0.isPinned == false })
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let pinned = [Message(isPinned: true), Message(isPinned: true), Message(isPinned: true)]
        let normal = [Message(isPinned: false), Message(isPinned: false), Message(isPinned: false)]
        sortedArray =  pinned + normal
        if let firstIndex = normalPinFirstIndex {
            print(firstIndex)
        }
    }
}
0 голосов
/ 02 января 2019

Я создал ту же ситуацию, в которой вы находитесь, проверьте этот код.

struct Message {
    var isPinned: Bool
}

var pinnedArray: [Message] = [Message(isPinned: true),Message(isPinned: true),Message(isPinned: true),Message(isPinned: true)]
var notPinnedArray: [Message] = [Message(isPinned: false),Message(isPinned: false),Message(isPinned: false),Message(isPinned: false)]

var sortedArray: [Message]  = pinnedArray + notPinnedArray // this will put pinned Array first then add the normal one after it so it would be [true, true, ture, true, false, false, false, false ]
var indexForFirstNormalMessage = pinnedArray.count //index for the first normal message is the count of the pinnedArray because array indexing starts at 0 and counting starts at 1 so  using the count of the pinned array as index in the sorted one, would get you the first normal message index.
print(indexForFirstNormalMessage) // 4

sortedArray.forEach {message in
    print(message)
}
/* Message(isPinned: true)
 Message(isPinned: true)
 Message(isPinned: true)
 Message(isPinned: true)
 Message(isPinned: false)
 Message(isPinned: false)
 Message(isPinned: false)
 Message(isPinned: false)*/
...