Is there an easy way to remove every nth element from a swift array. For example, in the array below:
是否有一种简单的方法可以从swift数组中删除第n个元素。例如,在下面的数组中:
thisArray = [2.0, 4.0, 3.0, 1.0, 4.5, 3.3, 1.2, 3.6, 10.3, 4.4, 2.0, 13.0]
If n = 3
and start count from first element would like to return:
如果n = 3,从第一个元素开始计数,则返回:
returnThis = [2.0, 4.0, 1.0, 4.5, 1.2, 3.6, 4.4, 2.0]
4 个解决方案
#1
3
// swift 3:
thisArray.enumerated().flatMap { index, element in index % 3 == 2 ? nil : element }
- Use
.enumerated()
to attach the indices - 使用. enum灵()附加索引
- Then use
flatMap()
to filter out items at indices 2, 5, 8, ... by returningnil
, and strip the index for the rest by returning justelement
. - 然后使用flatMap()过滤掉索引2、5、8、…通过返回nil,并通过返回just元素来删除其余的索引。
(If you are stuck with Swift 2, use .enumerate()
instead of .enumerated()
.)
(如果您使用的是Swift 2,请使用.enumerate()而不是. enumates()。
#2
2
You can compute the new array directly from the old array by adjusting the indices. For n=3
it looks like this:
可以通过调整索引直接从旧数组中计算新的数组。对于n=3,它是这样的:
0 1 2 3 4 5 6 7 8 ... old array index | | / / / / | | | | / / | | | | / / | | / / / / 0 1 2 3 4 5 6 ... new array index
Code:
代码:
let thisArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let n = 3
let newCount = thisArray.count - thisArray.count/n
let newArray = (0..<newCount).map { thisArray[$0 + $0/(n - 1)] }
print(newArray) // [1, 2, 4, 5, 7, 8, 10]
After taking n-1
elements from the old array you have to skip one element. This is achieved by adding $0/(n - 1)
to the (new) array index $0
in the map closure.
从旧数组中获取n-1元素后,必须跳过一个元素。这是通过将$0/(n - 1)添加到map闭包中的(新)数组索引$0来实现的。
#3
0
Since the Functional style solutions have already been posted I am using here an old fashion way approach
由于函数样式解决方案已经发布,所以我在这里使用了一种老式的方法
let nums = [2.0, 4.0, 3.0, 1.0, 4.5, 3.3, 1.2, 3.6, 10.3, 4.4, 2.0, 13.0]
var filteredNums = [Double]()
for elm in nums.enumerate() where elm.index % 3 != 2 {
filteredNums.append(elm.element)
}
#4
0
One way to achieve this is by using flatMap
which among other things it removes nils from the array, thus we'll simply return nil
for the indexes we want to remove:
实现这一点的一种方法是使用flatMap,它从数组中删除nils,因此我们只需为要删除的索引返回nil:
let n = 3
let arr = [2.0, 4.0, 3.0, 1.0, 4.5, 3.3, 1.2, 3.6, 10.3, 4.4, 2.0, 13.0]
let filteredArr = arr.enumerate().flatMap {$0.index % n == n - 1 ? nil : $0.element }
For swift 3:
为迅速3:
let filteredArr = thisArray.enumerated().flatMap {$0.offset % n == n - 1 ? nil : $0.element }
Generally speaking, you ignore the N-1
th element of the array.
一般来说,忽略数组的第n -1个元素。
A more functional solution can be achieved via strides:
一个更实用的解决方案可以通过跨步实现:
let filteredArr = (n-1).stride(to: arr.count, by: n).flatMap { arr[($0-n+1)..<$0] }
The approach here is to obtain the indexes that will be filtered out, and then join the slices between two consecutive filtered out indexes.
这里的方法是获取将被过滤掉的索引,然后在两个连续过滤掉的索引之间加入切片。
Or another approach, via reduce
, which is actually to what filter/map/flatMap reduce to:
或者另一种方法,通过reduce,实际上是过滤器/map/flatMap减少到:
let filteredArr = arr.enumerate().reduce([]) { $1.0 % n == n - 1 ? $0 : $0 + [$1.1] }
// or, both produce the same results
let filteredArr = arr.reduce((0,[])) { ($0.0 + 1, $0.0 % n == n - 1 ? $0.1 : $0.1 + [$1]) }.1
And not lastly, a mathematical approach: take the set of indexes in the array, substract the indexes that we don't want, built the result array from the sorted resulted indexes:
最后,一个数学方法:取数组中的一组索引,将我们不想要的索引进行细分,从排序的结果索引中构建结果数组:
let filteredArr = Set(0..<arr.count).subtract((n-1).stride(to: arr.count, by: n)).sort(<).map { arr[$0] }
#1
3
// swift 3:
thisArray.enumerated().flatMap { index, element in index % 3 == 2 ? nil : element }
- Use
.enumerated()
to attach the indices - 使用. enum灵()附加索引
- Then use
flatMap()
to filter out items at indices 2, 5, 8, ... by returningnil
, and strip the index for the rest by returning justelement
. - 然后使用flatMap()过滤掉索引2、5、8、…通过返回nil,并通过返回just元素来删除其余的索引。
(If you are stuck with Swift 2, use .enumerate()
instead of .enumerated()
.)
(如果您使用的是Swift 2,请使用.enumerate()而不是. enumates()。
#2
2
You can compute the new array directly from the old array by adjusting the indices. For n=3
it looks like this:
可以通过调整索引直接从旧数组中计算新的数组。对于n=3,它是这样的:
0 1 2 3 4 5 6 7 8 ... old array index | | / / / / | | | | / / | | | | / / | | / / / / 0 1 2 3 4 5 6 ... new array index
Code:
代码:
let thisArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let n = 3
let newCount = thisArray.count - thisArray.count/n
let newArray = (0..<newCount).map { thisArray[$0 + $0/(n - 1)] }
print(newArray) // [1, 2, 4, 5, 7, 8, 10]
After taking n-1
elements from the old array you have to skip one element. This is achieved by adding $0/(n - 1)
to the (new) array index $0
in the map closure.
从旧数组中获取n-1元素后,必须跳过一个元素。这是通过将$0/(n - 1)添加到map闭包中的(新)数组索引$0来实现的。
#3
0
Since the Functional style solutions have already been posted I am using here an old fashion way approach
由于函数样式解决方案已经发布,所以我在这里使用了一种老式的方法
let nums = [2.0, 4.0, 3.0, 1.0, 4.5, 3.3, 1.2, 3.6, 10.3, 4.4, 2.0, 13.0]
var filteredNums = [Double]()
for elm in nums.enumerate() where elm.index % 3 != 2 {
filteredNums.append(elm.element)
}
#4
0
One way to achieve this is by using flatMap
which among other things it removes nils from the array, thus we'll simply return nil
for the indexes we want to remove:
实现这一点的一种方法是使用flatMap,它从数组中删除nils,因此我们只需为要删除的索引返回nil:
let n = 3
let arr = [2.0, 4.0, 3.0, 1.0, 4.5, 3.3, 1.2, 3.6, 10.3, 4.4, 2.0, 13.0]
let filteredArr = arr.enumerate().flatMap {$0.index % n == n - 1 ? nil : $0.element }
For swift 3:
为迅速3:
let filteredArr = thisArray.enumerated().flatMap {$0.offset % n == n - 1 ? nil : $0.element }
Generally speaking, you ignore the N-1
th element of the array.
一般来说,忽略数组的第n -1个元素。
A more functional solution can be achieved via strides:
一个更实用的解决方案可以通过跨步实现:
let filteredArr = (n-1).stride(to: arr.count, by: n).flatMap { arr[($0-n+1)..<$0] }
The approach here is to obtain the indexes that will be filtered out, and then join the slices between two consecutive filtered out indexes.
这里的方法是获取将被过滤掉的索引,然后在两个连续过滤掉的索引之间加入切片。
Or another approach, via reduce
, which is actually to what filter/map/flatMap reduce to:
或者另一种方法,通过reduce,实际上是过滤器/map/flatMap减少到:
let filteredArr = arr.enumerate().reduce([]) { $1.0 % n == n - 1 ? $0 : $0 + [$1.1] }
// or, both produce the same results
let filteredArr = arr.reduce((0,[])) { ($0.0 + 1, $0.0 % n == n - 1 ? $0.1 : $0.1 + [$1]) }.1
And not lastly, a mathematical approach: take the set of indexes in the array, substract the indexes that we don't want, built the result array from the sorted resulted indexes:
最后,一个数学方法:取数组中的一组索引,将我们不想要的索引进行细分,从排序的结果索引中构建结果数组:
let filteredArr = Set(0..<arr.count).subtract((n-1).stride(to: arr.count, by: n)).sort(<).map { arr[$0] }