Following the instructions reported in the documented swift manual
http://swift-ios.co/standard-functions-in-swift/
I found the code the extract the index of a certain value of an array using
var languages = ["Swift", "Objective-C"]
find(languages, "Objective-C") == 1
find(languages, "Java") == nil
find([29, 85, 42, 96, 75], 42) == 2
The problem is that the output value doesn' t have the same type of the elements os the starting array, since the output in the console is (for the last line)
Optional(2)
What if I want to get the 2 as Int or Double?
It is Int? (a.k.a. Optional<Int>). You need to extract Int from it. You can use if-let syntax
if let index = find([29, 85, 42, 96, 75], 42) {
// index is Int
}
Related
I am trying to pair the duplicate elements of an array and count the pairs.
When given array is : [10, 20, 20, 10, 10, 30, 50, 10, 20], I'm expecting numberOfPairs to be 3. Because there are 2 pairs of 10s and 1 pair of 20.
My "if condition" is checking if current element's index is first index or not. If it is not the last index, it means that there is a duplicate of the current element. So I'am adding 1 to numberOfPairs.
For input [10, 20, 20, 10, 10, 30, 50, 10, 20], my numberOfPairs is 2 but it should be 3.
For input [1 1 3 1 2 1 3 3 3 3], myNumberOfPairs is not printing at all? But instead it should be 4.
My What am I missing here?
func sockMerchant(n: Int, ar: [Int]) -> Int {
// Write your code here
var array = ar
var numberOfPairs = 0
for i in 0..<array.count {
var element = array[i]
let indexOfLastElement = array.lastIndex(of: element)
let indexOfFirstElement = array.firstIndex(of: element)
print("indexOfLastElement is \(indexOfLastElement)")
print("indexOfFirstElement is \(indexOfFirstElement)")
if indexOfFirstElement != indexOfLastElement {
numberOfPairs += 1
array.remove(at: indexOfFirstElement!)
array.remove(at: indexOfLastElement!)
continue
}
return numberOfPairs
}
return numberOfPairs
}
You're mutating your array by calling remove(at:) at the same time as you're accessing it which is why you're having these weird side effects.
I assume you're trying to solve a Leetcode task (or something similar), so I won't provide a solution upfront. My suggestion for you is to think of an algorithm that doesn't involve changing the contents of the List while you're reading these contents of that same List.
I'm agree with #MartinR that in such cases you should place breakpoints and go throught your code line by line, glad you've found your mistake by yourself.
But also in terms of performance, lastIndex and firstIndex are very heavy operations, because they may go thought all items and find nothing, which makes Big O notation of your algorithm around O(log n). In such cases dictionary is widely used(if you're not much limited with the space).
You can use value as a key and count as a value for a dictionary and count all items, then just sum like this:
func sockMerchant(ar: [Int]) -> Int {
ar.reduce(into: [Int:Int]()) { map, value in
map[value, default: 0] += 1
}.reduce(0) { sum, count in
sum + count.value / 2
}
}
So, I've solved the problem as below, thanks to #Vym and #Martin R.
func sockMerchant(n: Int, ar: [Int]) -> Int {
// Write your code here
var array = ar
var numberOfPairs = 0
var newArray = [Int]()
var done = false
for i in 0..<array.count {
let element = array[i]
let indexOfLastElement = array.lastIndex(of: element)
let indexOfFirstElement = array.firstIndex(of: element)
if indexOfFirstElement != indexOfLastElement {
newArray.append(element)
numberOfPairs = newArray.count/2
done = true
}
}
if done == true {
return numberOfPairs
}
return numberOfPairs
}
I want to change subscript coordinates in an Array of Arrays [[Int]] in order to be able to address each value in a way similar to a spreadsheet, so assigning values, formulas across cells, etc.
Currently to address each value I need to subscript like table[2][1] = 12 or similar. I would like to subscript like a spreadsheet table[a][2] = 12, so that I can adapt long and complicated formulas in bigger speadsheets to similar tables using the same system used in spreadsheets.
The question is: how to change the subscript system in an efficient way? I send a simplified example to ilustrate the point
class ViewController: UIViewController {
var table = [[0, 1, 2, 3],
[1, 32, 44, 25],
[2, 12, 66, 43],
[3, 3, 4, 5]]
override func viewDidLoad() {
super.viewDidLoad()
print(table[2][1]) // 12
table[1][1] = 100
table[3][3] = table[1][1] * table[3][1] * 10
print(table[3][3])
printArray(table: table, j: 3)
}
// MARK: - Function
func printArray(table: [[Int]], j:Int) {
for i in 0...j {
print(table[i])
}
}
}
The closest solution I found is to use enums, like here:
enum Column:Int {
case a
case b
case c
// and so on
}
extension Array {
subscript(col:Column) -> Element {
get {
return self[col.rawValue]
}
set(newValue) {
self[col.rawValue] = newValue
}
}
}
var table = [[0, 1, 2, 3],
[1, 32, 44, 25],
[2, 12, 66, 43],
[3, 3, 4, 5]]
table[.a][2] = 12
let val = table[.a][2]
print (val)
Nevertheless, there are two little drawbacks:
you first have hard-code all the "column" letters you want to access to the Column enum.
then, something like table[5][.c] and table[.a][.b] will also be allowed - so you could access the rows via letter, not only the columns
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
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.
I have define an enum, and I want to use it as a key for a dictionary.
When I'm trying to access a value using the enum as a key, i get an error about the enum not being convertible to DictionaryIndex<Constants.PieceValue, Array<String>> where Constants.PieceValue is an enum that looks like this:
public enum PieceValue: Int {
case Empty = 0,
WKing = 16,
WQueen = 15,
WRook = 14,
WBishop = 13,
WKnight = 12,
WPawn = 11,
BKing = 26,
BQueen = 25,
BRook = 24,
BBishop = 23,
BKnight = 22,
BPawn = 21
}
I read a few threads but haven't found any clear answers.
I also declared the operator overloading function for the enum outside the Constants class.
func == (left:Constants.PieceValue, right:Constants.PieceValue) -> Bool {
return Int(left) == Int(right)
}
This is the line that Xcode complains about:
self.label1.text = Constants.pieceMapping[self.pieceValue][0]
Constants.pieceMapping has the following type: Dictionary<PieceValue, Array<String>>
That's the typical optional problem: when you query a dictionary, it returns an optional value, to account for cases when the key is not found. So this:
Constants.pieceMapping[self.pieceValue]
is of Array<String>? type. In order to access to that array, you first have to unwrap from the optional, using either forced unwrapping:
Constants.pieceMapping[Constants.PieceValue.BPawn]![0]
or in a safer way using optional binding:
if let array = Constants.pieceMapping[Constants.PieceValue.BPawn] {
let elem = array[0]
}