Can Somebody Give a Snippet of "Append If Not Exists" Method in Swift Array

Can somebody give a snippet of append if not exists method in swift array?

You can extend RangeReplaceableCollection, constrain its elements to Equatable and declare your method as mutating. If you want to return Bool in case the appends succeeds you can also make the result discardable. Your extension should look like this:

extension RangeReplaceableCollection where Element: Equatable {
@discardableResult
mutating func appendIfNotContains(_ element: Element) -> (appended: Bool, memberAfterAppend: Element) {
if let index = firstIndex(of: element) {
return (false, self[index])
} else {
append(element)
return (true, element)
}
}
}

Simple way to replace an item in an array if it exists, append it if it doesn't

Given your use case, in which you're always checking $0.<prop> == newthing.<prop>, you can lift this a little more by adding:

mutating func replaceOrAppend<Value>(_ item: Element, 
firstMatchingKeyPath keyPath: KeyPath<Element, Value>)
where Value: Equatable
{
let itemValue = item[keyPath: keyPath]
replaceOrAppend(item, whereFirstIndex: { $0[keyPath: keyPath] == itemValue })
}

You can then use it like:

struct Student {
let id: Int
let name: String
}

let alice0 = Student(id: 0, name: "alice")
let alice1 = Student(id: 1, name: "alice")
let bob = Student(id: 0, name: "bob")

var array = [alice0]

array.replaceOrAppend(alice1, firstMatchingKeyPath: \.name) // [alice1]
array.replaceOrAppend(bob, firstMatchingKeyPath: \.name) // [alice1, bob]

And of course if you do this a lot, you can keep lifting and lifting.

protocol Identifiable {
var id: Int { get }
}

extension Student: Identifiable {}

extension Array where Element: Identifiable {
mutating func replaceOrAppendFirstMatchingID(_ item: Element)
{
replaceOrAppend(item, firstMatchingKeyPath: \.id)
}
}

array.replaceOrAppendFirstMatchingID(alice0) // [alice1, alice0]

how to prevent arraylist from adding the same string twice?

Make sure the string isn't already in the array before appending, like this:

@IBAction func add(_ sender: Any) {
if !myArray.contains(name) {
myArray.append(name)
}
}

How to validate array value already exist or not

You can use contains(where:) to check if the array contains the element by comparing the unique properties in the class.

if !items.contains(where: {$0.url == fileUrl}) {
items.append(yourItem)
}

How to check if an element is in an array

Swift 2, 3, 4, 5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}

contains() is a protocol extension method of SequenceType (for sequences of Equatable elements) and not a global method as in
earlier releases.

Remarks:

  • This contains() method requires that the sequence elements
    adopt the Equatable protocol, compare e.g. Andrews's answer.
  • If the sequence elements are instances of a NSObject subclass
    then you have to override isEqual:, see NSObject subclass in Swift: hash vs hashValue, isEqual vs ==.
  • There is another – more general – contains() method which does not require the elements to be equatable and takes a predicate as an
    argument, see e.g. Shorthand to test if an object exists in an array for Swift?.

Swift older versions:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
println("yes")
}

Method signature to take the same array in array extension

Just simply pass parameter of type Array

extension Array {
func doSomethingWithAnotherArray(arr: Array) {
... // do something
}
}

[Int].doSomethingWithAnotherArray(arr: [Int]) // works
[Int].doSomethingWithAnotherArray(arr: [String]) // doesn't work

Avoid duplicates in Swift array

If you want to avoid duplicates why don't you use a Set anyway (Translation must conform to Hashable)?

var set = Set<Translation>()

However if you want to keep the array a more efficient way is to add an add method which filters the duplicates, Translation must conform to Equatable

func add(object: Translation) {
if !array.contains(object) {
array.append(object)
delegate?.newItemAdded()
}
}

Making a Set from the Array and then convert it back to Array is unnecessarily expensive.

How to append elements into a dictionary in Swift?

You're using NSDictionary. Unless you explicitly need it to be that type for some reason, I recommend using a Swift dictionary.

You can pass a Swift dictionary to any function expecting NSDictionary without any extra work, because Dictionary<> and NSDictionary seamlessly bridge to each other. The advantage of the native Swift way is that the dictionary uses generic types, so if you define it with Int as the key and String as the value, you cannot mistakenly use keys and values of different types. (The compiler checks the types on your behalf.)

Based on what I see in your code, your dictionary uses Int as the key and String as the value. To create an instance and add an item at a later time you can use this code:

var dict = [1: "abc", 2: "cde"] // dict is of type Dictionary<Int, String>
dict[3] = "efg"

If you later need to assign it to a variable of NSDictionary type, just do an explicit cast:

let nsDict = dict as! NSDictionary

And, as mentioned earlier, if you want to pass it to a function expecting NSDictionary, pass it as-is without any cast or conversion.

Appending dictionary values to array in Swift

You should only sort the keys and then use that array to select from the dictionary and append your sortedValues array. I made the sortedKeys into a local variable

func sortItems() {
let sortedKeys = self.dictionary.keys.sorted(by: >)

for key in sortedKeys {
if let obj = dictionary[key] {
self.sortedValues.append(obj)
}
}
}

I don't know if this will make a difference in regard to the crash but another way is to let the function return an array

func sortItems() -> [Object] {
let sortedKeys = self.dictionary.keys.sorted(by: >)
var result: [Object]()

for key in sortedKeys {
if let obj = dictionary[key] {
result.append(obj)
}
}
return result
}

and then call it

self.sortedValues = sortItems()

How to determine if one array contains all elements of another array in Swift?

Instead of iterating through arrays and doing filtering yourself, you can use NSSet to do all the work for you.

var list:Array<Int> = [1,2,3,4,5]
var findList:Array<Int> = [1,3,5]

let listSet = NSSet(array: list)
let findListSet = NSSet(array: findList)

let allElemtsEqual = findListSet.isSubsetOfSet(otherSet: listSet)

NSSet is a lot faster than arrays at checking if it contains any object. In fact it's what it's designed for.

Edit: Using Swift's built-in Set.

let list = [1,2,3,4,5]
let findList = [1,3,5]
let listSet = Set(list)
let findListSet = Set(findList)
//**Swift 4.2 and Above**
let allElemsContained = findListSet.isSubset(of: listSet)

//below versions
//let allElemsContained = findListSet.isSubsetOf(listSet)


Related Topics



Leave a reply



Submit