Repeating array in Swift - arrays

In Python I can create a repeating list like this:
>>> [1,2,3]*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Is there a concise way to do this in Swift?
The best I can do is:
1> var r = [Int]()
r: [Int] = 0 values
2> for i in 1...3 {
3. r += [1,2,3]
4. }
5> print(r)
[1, 2, 3, 1, 2, 3, 1, 2, 3]

You can create a 2D array and then use flatMap to turn it into a 1D array:
let array = [[Int]](repeating: [1,2,3], count: 3).flatMap{$0}
If you want to have a general way of doing this, here's an extension that adds an init method and a repeating method that takes an array which makes this a bit cleaner:
extension Array {
init(repeating: [Element], count: Int) {
self.init([[Element]](repeating: repeating, count: count).flatMap{$0})
}
func repeated(count: Int) -> [Element] {
return [Element](repeating: self, count: count)
}
}
let array = [1,2,3].repeated(count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
Note that with the new initializer you can get an ambiguous method call if you use it without providing the expected type:
let array = Array(repeating: [1,2,3], count: 3) // Error: Ambiguous use of ‛init(repeating:count:)‛
Use instead:
let array = [Int](repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
or
let array:[Int] = Array(repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
This ambiguity can be avoided if you change the method signature to init(repeatingContentsOf: [Element], count: Int) or similar.

With Swift 5, you can create an Array extension method in order to repeat the elements of the given array into a new array. The Playground sample code below shows a possible implementation for this method:
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
}
let array = [20, 11, 87]
let newArray = array.repeated(count: 3)
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]
If needed, you can also create an infix operator to perform this operation:
infix operator **
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
static func **(lhs: Array<Element>, rhs: Int) -> Array<Element> {
return lhs.repeated(count: rhs)
}
}
let array = [20, 11, 87]
let newArray = array ** 3
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]

You can use modulo operations for index calculations of your base collection and functional programming for this:
let base = [1, 2, 3]
let n = 3 //number of repetitions
let r = (0..<(n*base.count)).map{base[$0%base.count]}
You can create a custom overload for the * operator, which accepts an array on the left and an integer on the right side.
func * <T>(left: [T], right: Int) -> [T] {
return (0..<(right*left.count)).map{left[$0%left.count]}
}
You can then use your function just like in python:
[1, 2, 3] * 3
// will evaluate to [1, 2, 3, 1, 2, 3, 1, 2, 3]

Solution 1:
func multiplerArray(array: [Int], time: Int) -> [Int] {
var result = [Int]()
for _ in 0..<time {
result += array
}
return result
}
Call this
print(multiplerArray([1,2,3], time: 3)) // [1, 2, 3, 1, 2, 3, 1, 2, 3]
Solution 2:
let arrays = Array(count:3, repeatedValue: [1,2,3])
// [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
var result = [Int]()
for array in arrays {
result += array
}
print(result) //[1, 2, 3, 1, 2, 3, 1, 2, 3]

Related

Sum an array of arrays by position resulting in one array in Swift

I have an array of arrays of Int and I want to sum every value within all the values in the same position in a performing way. For example:
let array: [[Int]] = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
The result should be:
let result: [Int] = [11, 14, 11, 9]
If this is too complex, I can make all subarrays to have the same amount of elements.
My current soultion is the following but I believe it has to be a cleaner and more efficient way of doing it:
func sumElementsInSubArrays(_ array: [[Int]]) -> [Int] {
var result: [Int] = []
for subarray in array {
for (i, value) in subarray.enumerated() {
if result.count > (i) {
result[i] = result[i] + value
} else {
result[i] = value
}
}
}
return result
}
There may be several ways like HOF to deal with this situation but if you are new to it like me , you can do it like this :
Considering all the subArrays to have same number of element :
let array = [[1, 2, 3, 4], [5, 2, 7, 0] , [1, 7, 9, 4]]
var finalArray = [Int]()
for i in 0..<(array.first?.count ?? 0) {
var aElement = 0
array.forEach { aArray in
aElement += aArray[i]
}
finalArray.append(aElement)
}
//Final array should look like this at this point : [7, 11, 19, 8]
You could use a couple of nested loops (I don't think performance wise using reduce would be faster, thought it may look better/debatably be better for readability):
func sumElementsInSubArrays(_ array: [[Int]]) -> [Int] {
var result: [Int] = []
for subarray in array {
for (i, value) in subarray.enumerated() {
if result.count > i {
result[i] += value
} else {
result.append(value)
}
}
}
return result
}
print(sumElementsInSubArrays([[1, 2, 3], [4, 5], [6, 7, 8, 9]]))
print(sumElementsInSubArrays([]))
print(sumElementsInSubArrays([[]]))
Output:
[11, 14, 11, 9]
[]
[]

Optimize Swift function to find a specific set of combinations of 3 digits within a larger integer array

I'm working on a function that will help me quickly find all the upper structure triads (3-note chord) that I can add to a 4-note 7th chord to create a larger compound chord, as well of the roots and names of each triad. The example I'm testing right now is a 13#11 chord, which has the following degrees in a 12-note octave (when the root is 0): [0, 2, 4, 6, 7, 9, 10]*
*side note: [0, 4, 6, 7, 9, 10] would also match as a 13#11.
The base 7th chord is a dominant 7th: [0, 4, 7, 9].I already know which triads complete the chord: a major triad on the 9th, [2, 6, 9], and a diminished triad on the #11, 0, 6, 9 (only the 6 (#11th) and 9 (13th) are actually necessary to build a 13#11 chord; the 2 (9th) is optional).
I actually already have a function that will give me these results, I'm just wondering if there's a faster/more efficient way to do it? It just feels a little bulky/clunky right now. Any help would be appreciated.
Thanks!
Jake
extension Int {
func degreeInOctave() -> Int {
switch self {
case 0...11:
return self
case 12...:
return self - 12
default:
return self + 12
}
}
}
var ust: [Int] = [0, 2, 4, 6, 7, 9, 10]
let maj = [0, 4, 7]
let min = [0, 3, 7]
let aug = [0, 4, 8]
let dim = [0, 3, 6]
let sus4 = [0, 5, 7]
let sus2 = [0, 2, 7]
let triadDegs = [maj, min, aug, dim, sus4, sus2]
var triadRoots: [Int] = []
var triadQualities: [String] = []
func findUpperStructureTriads(degs: [Int]) {
let degCount = degs.count
var firstIndex = 0
while firstIndex < (degCount - 2) {
var secondIndex = firstIndex + 1
while secondIndex < (degCount - 1) {
var thirdIndex = secondIndex + 1
while thirdIndex < (degCount) {
var threeNoteGroup = [degs[firstIndex], degs[secondIndex], degs[thirdIndex]]
func checkForTriad(triad: [Int]) -> Bool {
if triadDegs.contains(triad) {
switch triad {
case maj:
triadQualities.append("major")
case min:
triadQualities.append("minor")
case aug:
triadQualities.append("augmented")
case dim:
triadQualities.append("diminished")
case sus4:
triadQualities.append("sus4")
case sus2:
triadQualities.append("sus2")
default:
()
}
return true
} else {
return false
}
}
if threeNoteGroup.contains(6), threeNoteGroup.contains(9){
var inversionCount = 0
var newGroup = threeNoteGroup.map {$0 - threeNoteGroup[0]}
while inversionCount < 3 {
func invert() {
newGroup = newGroup.map {($0 - newGroup[1]).degreeInOctave()}
let newlast = newGroup.remove(at: 0)
newGroup.append(newlast)
}
if checkForTriad(triad: newGroup) {
print(threeNoteGroup, threeNoteGroup[inversionCount])
triadRoots.append(threeNoteGroup[inversionCount])
break
}
invert()
inversionCount += 1
}
}
thirdIndex += 1
}
secondIndex += 1
}
firstIndex += 1
}
for i in 0...(triadRoots.count - 1) {
print(triadRoots[i], triadQualities[i])
}
}
findUpperStructureTriads(degs: ust)
outputs:
[0, 6, 9] 6
[2, 6, 9] 2
6 diminished
2 major

Swift 3 Remove objects from an array that are present in another array using set and maintaining order [duplicate]

This question already has answers here:
iOS swift remove elements of an array from another array
(9 answers)
Closed 5 years ago.
Array1 = [1, 2, 3, 4, 5, 6]
Array2 = [1,5]
I want to get:
Array1 = [2, 3, 4, 6]
I want to do this by using Set because these arrays may get larger.
Also it is important that I maintain the order of the array.
Create a set with all elements from the second array,
then filter the first array to get only the elements which are not
in the set:
let array1 = [5, 4, 1, 2, 3, 4, 1, 2]
let array2 = [1, 5]
let set2 = Set(array2)
let result = array1.filter { !set2.contains($0) }
print(result) // [4, 2, 3, 4, 2]
This preserves the order (and duplicate elements) from the first
array. Using a set is advantageous if the second array can be large,
because the lookup is faster.
var array1 = [1, 2, 3, 4, 5, 6]
var array2 = [1,5]
var arrayResult = array1.enumerated()
.filter { !array2.contains($0.0 + 1) }
.map { $0.1 }
print(arrayResult)
[2, 3, 4, 6]
Another ways to achieve the same result:
1. User filter
let arrayResult = array1.filter { element in
return !array2.contains(element)
}
2. Use Sort
array2.sorted(by: >).forEach { if $0 < self.array1.count { self.array1.remove(at: $0) } }
Remove elements using indexes array:
Array of Strings and indexes
let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
let indexAnimals = [0, 3, 4]
let arrayRemainingAnimals = animals
.enumerated()
.filter { !indexAnimals.contains($0.offset) }
.map { $0.element }
print(arrayRemainingAnimals)
//result - ["dogs", "chimps", "cow"]
Array of Integers and indexes
var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
let indexesToRemove = [3, 5, 8, 12]
numbers = numbers
.enumerated()
.filter { !indexesToRemove.contains($0.offset) }
.map { $0.element }
print(numbers)
//result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
Remove elements using element value of another array
Arrays of integers
let arrayResult = numbers.filter { element in
return !indexesToRemove.contains(element)
}
print(arrayResult)
//result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
Arrays of strings
let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
let arrayRemoveLetters = ["a", "e", "g", "h"]
let arrayRemainingLetters = arrayLetters.filter {
!arrayRemoveLetters.contains($0)
}
print(arrayRemainingLetters)
//result - ["b", "c", "d", "f", "i"]
Use the filter function
let result = Array1.filter { element in
return !Array2.contains(element)
}
(Note: because you added to your question and maintaining order then my answer is not right anymore, because Set don't preserve the order. then the filter answers are a better fit)
use subtracting from a Set:
array1 = Array(Set(array1).subtracting(Set(array2)))
you can add this as an operator :
Using the Array → Set → Array method mentioned by Antonio, and with the convenience of an operator, as freytag pointed out, I've been very satisfied using this:
// Swift 3.x
func - <Element: Hashable>(lhs: [Element], rhs: [Element]) -> [Element]
{
return Array(Set<Element>(lhs).subtracting(Set<Element>(rhs)))
}
quoted from: https://stackoverflow.com/a/42679608/1930509
let array1 = [1, 2, 3, 4, 5, 6]
let array2 = [1,5]
let array3 = array1.reduce([]) { array2.contains($1) ? $0 : $0 + [$1] }
print(array3) // "[2, 3, 4, 6]\n"

How can I get the largest value from an integer array in a dictionary of arrays

I am trying to get the largest value in a dictionary of arrays and I need also get the key of that array.
This is how I get the largest value:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
I would use max method in your dictionary values and get the maximum value from the resulting tuple values:
if let result = interestingNumbers.max(by: {$0.value.max() ?? 0 < $1.value.max() ?? 0}),
let maxValue = result.value.max() {
print(result.key) // "Square\n"
print(result.value) // "[1, 4, 9, 16, 25]\n"
print(maxValue) // 25
}
Why don't you use a tuple to hold the largest value?
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest: (kind: String?, number: Int) = (nil, 0)
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest.number {
largest = (kind, number)
}
}
}
Which can be further simplified to:
var largest: (kind: String?, number: Int) = (nil, 0)
for (kind, numbers) in interestingNumbers {
let max = numbers.max() ?? 0
if max > largest.number {
largest = (kind, max)
}
}
Another method is to flatten the values first into a (kind, number) sequence:
let flattened = interestingNumbers
.map { (kind, numbers) in numbers.map { (kind, $0) } }
.joined()
let largest = flattened.max(by: { $0.1 < $1.1} )
print(largest)
or you can realize that only the maximum value in every array is the most important, therefore :
let largestPerKind = interestingNumbers
.map { (kind, numbers) in (kind, numbers.max() ?? 0) }
let largest = largestPerKind.max(by: { $0.1 < $1.1} )
print(largest)
You can use Swift function's for that.
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
if let value = interestingNumbers.map ({ ($0, $1.max() ?? 0) }).max(by: { $0.1 < $1.1 }) {
print(value.0, value.1) // Square 25
}
Let's go with step by step
First I have created array of tuple with type [(String, Int)], with first place it will store group and on second place it will store max value from its corresponding array.
let array = interestingNumbers.map ({ ($0, $1.max() ?? 0) })
//[("Fibonacci", 8), ("Square", 25), ("Prime", 13)]
Now find the max Int from the array of tuple.
if let value = array.max(by: { $0.1 < $1.1 }) {
print(value.0, value.1) //Will print group here it is "Square 25"
}
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var largest_kind : String? =nil
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
largest_kind = kind
}
}
}

How to remove elements from array that match elements in another array

How to remove elements from array that match elements in another array?
Assume we have an array and we loop through it and find out which elements to remove:
var sourceItems = [ ... ]
var removedItems = [SKShapeNode]()
for item : SKShapeNode in sourceItems {
if item.position.y > self.size.height {
removedItems.append(item)
item.removeFromParent()
}
}
sourceItems -= removedItems // well that won't work.
You can use the filter function.
let a = [1, 2, 3]
let b = [2, 3, 4]
let result = a.filter { element in
return !b.contains(element)
}
result will be [1]
Or more succinctly...
let result = a.filter { !b.contains($0) }
Check out the Swift Standard Library Reference
Or you can use the Set type.
let c = Set<Int>([1, 2, 3])
let d = Set<Int>([2, 3, 4])
c.subtract(d)
Be mindful if using the Set option, that your results only be unique values and will not maintain the initial ordering, if that matters to you, whereas the Array filter option will maintain the initial array's order, at least what elements remain.
Swift 3
let c = Set<Int>([65, 1, 2, 3, 1, 3, 4, 3, 2, 55, 43])
let d = Set<Int>([2, 3, 4])
c.subtracting(d)
c = {65, 2, 55, 4, 43, 3, 1}
d = {2, 3, 4}
result = {65, 55, 43, 1}

Resources