Remove duplicates from a NSMutableArray with objects added in a 'for' loop
I believe you want to be using an NSOrderedSet
. Here's the documentation on it:
http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html
NSMutableArray remove element at row and rearrange all the rows after that
This happens automatically when you call removeObjectAtIndex. From the class reference documentation:
To fill the gap, all elements beyond
index are moved by subtracting 1 from
their index.
Details of using fast enumeration on a copy of an NSMutableArray to remove objects
Copying an array does a "shallow copy". It creates a new array object, then stores pointers to the objects in the first array. It does not create new objects.
Think of an array like an address book. It lists the addresses of your friends' houses. If I make a copy of your address book, then I have a copy of the list of the addresses. The address books do not contain houses.
If I erase an entry from my copy of the address book, it does not erase the same entry from your address book. Nor does it destroy any houses.
In your loop 2 code, you are looping through the copy, then telling your original array to delete certain objects. They are deleted from the original array, but not from the copy. (Which is good, because as you say, mutating an array as you iterate through it causes a crash.)
Note that arrays can contain more than one pointer to the same object, just like addresses can contain the same address more than once. (If a friend changes her name when she gets married, you might write her into your address under he married name and leave the entry under her maiden name as well. Both addresses point to the same house.)
Note that the removeObject
method that you are using removes ALL entries for an object. It's like you're saying "erase every entry in my address book for 123 Elm street". If you only want to remove one entry of a duplicate set then you need to use removeObjectAtIndex instead, and you would need to change your code to make that work.
Swift code problem - trying to cast objects out from a NSMutableArray as a custom object
Better approach would be to use JSONDecoder() instead of a JSONSerailizer. Try using the following code.
struct User: Codable {
var userId, firstName, lastName, userSessionId: String
enum CodingKeys: String, CodingKey {
case userId = "Userid"
case firstName = "First_Name"
case lastName = "Last_Name"
case userSessionId = "Session_ID"
}
}
func parseJSON(_ data: Data) {
do {
let users = try JSONDecoder().decode([User].self, from: data)
users.forEach { user in
print("users first name:", user.firstName)
}
} catch {
print(error.localizedDescription)
}
}
Remove Specific Array Element, Equal to String - Swift
You can use filter() to filter your array as follow
var strings = ["Hello","Playground","World"]
strings = strings.filter { $0 != "Hello" }
print(strings) // "["Playground", "World"]\n"
edit/update:
Xcode 10 • Swift 4.2 or later
You can use the new RangeReplaceableCollection
mutating method called removeAll(where:)
var strings = ["Hello","Playground","World"]
strings.removeAll { $0 == "Hello" }
print(strings) // "["Playground", "World"]\n"
If you need to remove only the first occurrence of an element we ca implement a custom remove method on RangeReplaceableCollection
constraining the elements to Equatable
:
extension RangeReplaceableCollection where Element: Equatable {
@discardableResult
mutating func removeFirst(_ element: Element) -> Element? {
guard let index = firstIndex(of: element) else { return nil }
return remove(at: index)
}
}
Or using a predicate for non Equatable
elements:
extension RangeReplaceableCollection {
@discardableResult
mutating func removeFirst(where predicate: @escaping (Element) throws -> Bool) rethrows -> Element? {
guard let index = try firstIndex(where: predicate) else { return nil }
return remove(at: index)
}
}
var strings = ["Hello","Playground","World"]
strings.removeFirst("Hello")
print(strings) // "["Playground", "World"]\n"
strings.removeFirst { $0 == "Playground" }
print(strings) // "["World"]\n"
Remove objects with duplicate properties from Swift array
I am going to suggest 2 solutions.
Both approaches will need Post
to be Hashable
and Equatable
Conforming Post to Hashable and Equatable
Here I am assuming your Post
struct (or class) has an id
property of type String
.
struct Post: Hashable, Equatable {
let id: String
var hashValue: Int { get { return id.hashValue } }
}
func ==(left:Post, right:Post) -> Bool {
return left.id == right.id
}
Solution 1 (losing the original order)
To remove duplicated you can use a Set
let uniquePosts = Array(Set(posts))
Solution 2 (preserving the order)
var alreadyThere = Set<Post>()
let uniquePosts = posts.flatMap { (post) -> Post? in
guard !alreadyThere.contains(post) else { return nil }
alreadyThere.insert(post)
return post
}
NSMutablearray move object from index to index
id object = [[[self.array objectAtIndex:index] retain] autorelease];
[self.array removeObjectAtIndex:index];
[self.array insertObject:object atIndex:newIndex];
That's all. Taking care of the retain count is important, since the array might be the only one referencing the object.
How do you clear attributes from NSMutableAttributedString?
You can remove all of the attributes like this:
NSMutableAttributedString *originalMutableAttributedString = //your string…
NSRange originalRange = NSMakeRange(0, originalMutableAttributedString.length);
[originalMutableAttributedString setAttributes:@{} range:originalRange];
Note that this uses setAttributes (not add). From the docs:
These new attributes replace any attributes previously associated with the characters in
aRange
.
If you need to do any of it conditionally, you could also enumerate the attributes and remove them one-by-one:
[originalMutableAttributedString enumerateAttributesInRange:originalRange
options:kNilOptions
usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
[attrs enumerateKeysAndObjectsUsingBlock:^(NSString *attribute, id obj, BOOL *stop) {
[originalMutableAttributedString removeAttribute:attribute range:range];
}];
}];
According to the docs this is allowed:
If this method is sent to an instance of
NSMutableAttributedString
, mutation (deletion, addition, or change) is allowed.
Swift 2
If string
is a mutable attributed string:
string.setAttributes([:], range: NSRange(0..<string.length))
And if you want to enumerate for conditional removal:
string.enumerateAttributesInRange(NSRange(0..<string.length), options: []) { (attributes, range, _) -> Void in
for (attribute, object) in attributes {
string.removeAttribute(attribute, range: range)
}
}
How can I conform to the Strideable protocol in Swift?
Here's a definition of the protocol: Stridable
You can implement it like this:
final class Foo: Strideable {
var value: Int = 0
init(_ newValue: Int) { value = newValue }
func distanceTo(other: Foo) -> Int { return other.value - value }
func advancedBy(n: Int) -> Self { return self.dynamicType(value + n) }
}
func ==(x: Foo, y: Foo) -> Bool { return x.value == y.value }
func <(x: Foo, y: Foo) -> Bool { return x.value < y.value }
let a = Foo(10)
let b = Foo(20)
for c in stride(from: a, to: b, by: 1) {
println(c.value)
}
You need to provide the functions distanceTo
, advancedBy
and the operators ==
and <
. There is more information about these functions in the documentation I linked.
Related Topics
How to Make a Segue to Second Item of Tab Bar
Property with '= {Return}()' or '{Return}'
How to Get Notification Authorization Status in Swift 3
Swift Struct with Lazy, Private Property Conforming to Protocol
Set Uitextfield Placeholder Color Programmatically
How to Get Part of a String in Swift
Generic Method Override Not Working in Swift
Showing Notification Banner on MAC with Swift
Swift- How to Display Image Over Button
How to Increase the Scope of Variables in Switch-Case/Loops in Swift
Swift: Specialize Method of Generic Class for Function Types
Type Check Operator (Is) for Check VS Homogenous Protocol: Why Can This Be Done for Optionals
Spritekit: Howto Make Holes in Layer with Blendmode
Avaudiosinknode with Non-Default, But Still Device-Native Sample Rates
Custom Uitabbar Unselected Item's Color
How to Pass a Class and Method to Create an Instance of a Class
Changing The Color of a Button in Swiftui on Tvos
Sf Symbols Hierarchical, Palette, and Multicolor Rendering Mode Colors