How to remove one duplicate value in an array? - ios

I have two arrays for which I am comparing [Int]
let filter = strongAgainstArray.filter{weakAgainstArray.contains($0)}
This returns an array of common values in the 2 arrays. I then want to go through and remove those values from each array, which I'm doing like so
for item in filter {
for var i = 0; i < strongAgainstArray.count; i += 1 {
if item == strongAgainstArray[i] {
strongAgainstArray.removeAtIndex(i)
print("Removing a Strong against index \(item)")
}
}
for var i = 0; i < weakAgainstArray.count; i += 1 {
if item == weakAgainstArray[i] {
weakAgainstArray.removeAtIndex(i)
print("Removing a Weak against index \(item)")
}
}
}
This works fine, but let's say one of my arrays contains two entries for 12 as an example. How do I only remove one of them? As it stands, all entries of 12 are being removed entirely.
EDIT
I'm now comparing my two arrays using
let commonValues = Array(Set(strongAgainstArray).intersect(weakAgainstArray))
and then those commonValues from each array with
cleanStrongAgainstArray = Array(Set(strongAgainstArray).subtract(Set(commonValues)).sort())
cleanWeakAgainstArray = Array(Set(weakAgainstArray).subtract(Set(commonValues)).sort())
This is a much better overall solution, but I'm still eventually running into the same issue, albeit slightly different than before.
In the playground, for example...
let array = [7,7,9]
let test = Array(Set(array))
test comes back containing [7, 9], and I need to keep that extra 7. How do I do that?

If the order of the arrays aren't important then you can easily achieve the whole solution using Sets:
let dirtyArray = [1,4,6,1,56,4,4,66,23,3,3,12]
let dirtyArray1 = [3,1,6,99,54]
let cleanArray = Array(Set(dirtyArray).union(Set(dirtyArray1)))
print (cleanArray)
[12, 54, 23, 4, 6, 66, 99, 56, 1, 3]

If order is important, use NSOrderedSet:
let strongAgainstArray = [1, 2, 3, 4]
let weakAgainstArray = [3, 4, 5, 6]
let result = NSOrderedSet(array: (strongAgainstArray + weakAgainstArray)).array

Related

Two arrays in key and value in Dictionary swift

I have two Int arrays, for example:
array1 = [1, 2, 3, 4] as Int
array2 = [10, 20, 30, 40] as Int
for work I need create Dictionary where Key - it's element from array1 and Value - it's element from array2, in my example - [1:10, 2:20, 3:30, 4:40] as [Int:Int].
So, when I create loop:
for i in 0..<arrayOfKeys.count {
dictionaryOfData[arrayOfKeys[i]] = arrayOfValues[i]
}
i see only last [4:40], but I know that I must have the Dictionary with 4 keys-values.
Give me, please, advise, how to do it in swift?!
upd, i find my problem - keys MUST be unique! So, thanks a lot for your answer and i knew about zip in swift
Try this:
let array1 = [1, 2, 3, 4]
let array2 = [10, 20, 30, 40]
var dict = [Int: Int]()
zip(array1, array2).forEach { dict[$0] = $1 }
print(dict)
Few solutions off the top of my head:
Init Arrays + Dict
let arrayOfValues = [1,2,3,4]
let arrayOfKeys = [1,2,3,4]
var arrayOfDict = [Int:Int]()
For loop solution:
for i in 0..<arrayOfKeys.count {
if i < arrayOfValues.count {
let key = arrayOfKeys[i]
let value = arrayOfValues[i]
arrayOfDict[key] = value
}
}
Using zip method solution:
for (key, value) in zip(arrayOfValues, arrayOfKeys) {
arrayOfDict[key] = value
}
From apple docs:
zip: A sequence of pairs built out of two underlying sequences, where
the elements of the ith pair are the ith elements of each underlying
sequence.(iOS (9.0 and later))
If you can't use Zip you can enumerate your array if both arrays have the same number of elements:
let array1 = [1, 2, 3, 4]
let array2 = [10, 20, 30, 40]
var result: [Int:Int] = [:]
array1.enumerate().forEach{ result[$0.element] = array2[$0.index] }
result // [2: 20, 3: 30, 1: 10, 4: 40]
Here is an updated answer for Swift 4 taken from www.tutorialspoint.com:
let cities = ["Delhi", "Bangalore", "Hyderabad"]
let distances = [2000, 10, 620]
let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, distances))

Swift Define Array with more than one Integer Range one liner

I have an Array which I have defined
var array: [Int] = Array(1...24)
I then add
array.insert(9999, atIndex: 0)
I would like to do something like
var array: [Int] = Array(9999...9999,1...24)
Is this possible ?
You could simply concatenate the arrays created from each range:
let array = Array(10 ... 14) + Array(1 ... 24)
Alternatively:
let array = [10 ... 14, 1 ... 4].flatMap { $0 }
which has the small advantage of not creating intermediate arrays
(as you can see in the open source implementation https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceAlgorithms.swift.gyb).
As MartinR mentioned, you could simply concenate arrays using the + operator; and if this method is an answer for you, than this thread is a duplicate (see MartinR:s link), and should be closed.
If you explicitly wants to initialize an Int array using several ranges at once (see e.g. hola:s answer regarding array of ranges), you can make use of reduce as follows
let arr = [1...5, 11...15].reduce([]) { $0.0 + Array($0.1) }
Or, alternatively, flatten
var arr = Array([1...5, 11...15].flatten())
Both the above yields the following result
print(arr.dynamicType) // Array<Int>
print(arr) // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
For an array of ranges you define the array as
let array: [Range<Int>] = [0...1, 5...100]
and so on and so forth.

How to remove single object in array from multiple matching object

var testarray = NSArray()
testarray = [1,2,2,3,4,5,3]
print(testarray)
testarray.removeObject(2)
I want to remove single object from multiple matching object like
myArray = [1,2,2,3,4,3]
When I remove
myArray.removeObject(2)
then both objects are deleted. I want remove only single object.
I tried to use many extension but no one is working properly. I have already used this link.
Swift 2
Solution when using a simple Swift array:
var myArray = [1, 2, 2, 3, 4, 3]
if let index = myArray.indexOf(2) {
myArray.removeAtIndex(index)
}
It works because .indexOf only returns the first occurence of the found object, as an Optional (it will be nil if object not found).
It works a bit differently if you're using NSMutableArray:
let nsarr = NSMutableArray(array: [1, 2, 2, 3, 4, 3])
let index = nsarr.indexOfObject(2)
if index < Int.max {
nsarr.removeObjectAtIndex(index)
}
Here .indexOfObject will return Int.max when failing to find an object at this index, so we check for this specific error before removing the object.
Swift 3
The syntax has changed but the idea is the same.
Array:
var myArray = [1, 2, 2, 3, 4, 3]
if let index = myArray.index(of: 2) {
myArray.remove(at: index)
}
myArray // [1, 2, 3, 4, 3]
NSMutableArray:
let myArray = NSMutableArray(array: [1, 2, 2, 3, 4, 3])
let index = myArray.index(of: 2)
if index < Int.max {
myArray.removeObject(at: index)
}
myArray // [1, 2, 3, 4, 3]
In Swift 3 we call index(of:) on both Array and NSMutableArray, but they still behave differently for different collection types, like indexOf and indexOfObject did in Swift 2.
Swift 5: getting index of the first occurrence
if let i = yourArray.firstIndex(of: yourObject) {
yourArray.remove(at: i)
}
If you want to remove all duplicate objects then you can use below code.
var testarray = NSArray()
testarray = [1,2,2,3,4,5,3]
let set = NSSet(array: testarray as [AnyObject])
print(set.allObjects)

Sum progression in an array Swift

I have an basic Int array
Array = [8, 9, 8]
How do i sum all of its values progressively so that the end result would look like this
EndResult = [8, 17, 25]
Tried using for and while loops, but to no avail.
NB: Basic array[0] + array[1] advices will not work. I'm looking for something automatic like a loop solution.
Looking forward to your advices.
Thanks!
May be this:
var arr = [8, 9, 8]
for i in 1..<arr.count {
arr[i] += arr[i-1]
}
print(arr)
Probably there are better ways than this one, but it works
var array = [8, 9, 8]
var result = [Int]()
for i in 0..<array.count{
var temp = 0;
for j in 0...i{
temp+=array[j]
}
result.append(temp)
}
print(result) //[8, 17, 25]
You could use a reduce function in Swift to accomplish this. Note that you can't really do it with map, because you would need to know what the previous call to the map function returned, keep state in a variable outside the map function (which seems dirty), or loop over your array for every map function call.
let array = [8, 9, 8]
let results = array.reduce((0, []), combine: { (reduction: (lastValue: Int, values: Array<Int>), value: Int) in
let newValue = reduction.lastValue + value
return (newValue, reduction.values + [newValue])
}).1

NSRange array of odd or even count

I have an array of 977 of data, I've been trying to split it to 20 section in UITableView but i cannot get it correct, i am trying to do it dynamically. like if i got an array of 312 or 32 or 545 the equation should divide it, and add the last odd elements in array, I'm placing the new data in array of arrays.
So here is what I'm doing :
var dataof977 = Mydata()
var mutA = NSMutableArray()
for (var i = 0; i < 19; i++)
{
var halfArray : NSArray!
var theRange = NSRange()
theRange.location = i*19;
theRange.length = dataof977.afa.count / 19
halfArray = dataof977.afa.subarrayWithRange(theRange)
mutA.addObject(halfArray)
}
Note : dataof977 is reference of class and afa is a String array.
What am i missing here ?s
Three things:
You need to start each location where the previous left off. To do this, introduce a location variable to keep track of where you are in the original array.
Some of your sections will need more items since your count might not be a multiple of 20. I think your best best is to give the first n sections an extra item to make up for the leftovers.
Your loop needs to iterate 20 times, not 19. I have changed it to use for in which is better Swift style.
var mutA = NSMutableArray()
let sublength = dataof977.afa.count / 20
let leftovers = dataof977.afa.count % 20
// location of each new subarray
var location = 0
for i in 0..<20
{
var length = sublength
// The first sections will have 1 more each
if i < leftovers {
length++
}
let theRange = NSMakeRange(location, length)
let halfArray = dataof977.afa.subarrayWithRange(theRange)
mutA.addObject(halfArray)
// move location up past the items we just added
location += length
}
If you have the possibility to work with Swift arrays instead of NSArray, you can use stride to iterate by steps and divide an array in equal parts with the remainder elements in the last array:
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
extension Array {
func splitBy(subSize: Int) -> [[Element]] {
return 0.stride(to: self.count, by: subSize).map { startIndex in
let endIndex = startIndex.advancedBy(subSize, limit: self.count)
return Array(self[startIndex ..< endIndex])
}
}
}
let chunks = arr.splitBy(5)
print(chunks) // [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12]]
Note: this is for Swift 2.
You are only doing 19 iterations, not 20.
for var i = 0; i < 20; i++
You are taking one 19th of the data count, not one 20th. You are repeating the length calculation 19 times in the loop, which is redundant.
It would be easier to dispense with NSRange. Just iterate though all array elements, keep a counter up to the pre-calculate subarray size, and once it reaches the critical number, reset it to zero and start a new subarray to add to your result array.
This will presumably perform better if you use Swift arrays, but this is not strictly necessary.

Resources