Reputation: 767
I have two arrays, which are used consecutively.
var pinnedMessage: [Message]
var normalMessage: [Message]
I add the pinned messages to the first array and normal ones to the second. bu I always use both arrays Consecutive. so when I use them I make a new array, first append pinned messages then normal messages.
var newArray: [Message] = []
newArray.append(pinnedMessage)
newArray.append(normalMessage)
Another way is that I put both messages in one array and then sort them based on if their isPinned
property.
GlobalArray.sort { $0.isPinned && !$1.isPinned }
I also should know where is the index of first normal message. so I have a variable for that too.
I don't think if these ideas are ok. Should I use linked list or other data structure?
Upvotes: 0
Views: 95
Reputation: 12023
You can create a single array with both pinned and normal messages added consecutively and use Swift 4.2 firstIndex(where:)
method on Collections
to get the first index of normal message
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)
}
if you're doing it in UIViewController
then can use didSet
observer on the sortedArray
to set the firstIndex
of normal message
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)
}
}
}
Upvotes: 0
Reputation: 2338
Rather than using any of the alternatives you've listed, you could instead alter the way that you access your arrays. You can use a helper function, taking a closure as an argument, to process each element in the arrays:
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)
}
If you also need to know the type of the message, you should either process the arrays individually, without a helper function, or let your closure take another argument:
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)
}
Using this kind of method, frees you from the disadvantage of concatenating the two arrays: memory and performance overhead.
If you're displaying these messages as if they're in one array, the index of the first normal message, will simply be after the index of the last message in the pinnedMessages
array. pinnedMessages.count
will be equal to that array's last index + 1, equalling the first index of the normal messages.
Upvotes: 1
Reputation: 5088
I have created the same situation you are in check out this code.
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)*/
Upvotes: 0