What is the Swift equivalent of C#/.NET/LINQ's Enumerable.All method? - swift

I want a function that applies a given function to a sequence and returns true iff the given function returns true for every element of the sequence, like Enumerable.All from the C#/.NET/LINQ world.

Building up on Jon's answer: You can use contains()
instead of an (explicit) loop:
extension SequenceType {
func all(#noescape predicate: (Self.Generator.Element) throws -> Bool)
rethrows -> Bool {
return !(try contains { !(try predicate($0)) })
}
}

There isn't a built-in function to do this, but you can easily add your own as a protocol extension method:
extension SequenceType {
func all(#noescape predicate: (Self.Generator.Element) throws -> Bool)
rethrows -> Bool {
for i in self {
if !(try predicate(i)) { return false }
}
return true
}
}
and then use it on a sequence like:
let allPositive = [1, 2, 3].all { $0 > 0 }

Not sure if this helps, but you can achieve the same outcome using reduce. Here's a quick playground I put together to prove the concept:
let nums = [2, 2, 3, 4]
// Will only evaluate to true if all numbers are even.
let allEven = nums.reduce(true) {
if !$0 || $1 % 2 != 0 {
return false
}
return true
}

Related

How to invoke any swift function conditionally (without if block)

I want to write a general-purpose Swift function that serves the following simple purpose:
Take any function as argument
Take a Bool argument
If the bool argument is TRUE, invoke the input function with its args. Otherwise No-op.
The purpose is to eliminate a lot of clumsy if statements in the code that meet a specific criteria.
Something like:
typealias ClosureType = (Any...) -> Any. // Notice the variable argument of any kind
func invokeIfConditionIsTrue(closure: Closure, condition: Bool) {
if condition {
if let myFunc = closure as? ClosureType {
myFunc()
print("executed")
} else {
print("not executed")
}
}
}
func testIntToInt(i: Int) -> Int {
return i*i
}
func testIntToDouble(i: Int) -> Double {
return Double(i*i)
}
invokeIfConditionIsTrue(testIntToInt, true). // executed
invokeIfConditionIsTrue(testIntToDouble, false). // not executed
However, I am struggling to come up with syntax that will enable the argument passing to the input myFunc() func.
The example is pretty basic, and my input function closure could be accepting and emitting any type of input/outputs, including structs, classes and objective c stuff.
I have a hunch this is possible via a mechanism called function object, but I am not familiar enough with it.
Should I reinvent the wheel, or is there already a library/known way which is doing it successfully, and I am missing out?
I have no idea why you think
invokeIfConditionIsTrue(testIntToInt, condition)
is somehow superior to
if condition { result = testIntToInt(n) }
Or
result = condition ? testIntToInt(n) : 0
but what you want is pretty much impossible unless you wrap the function in a closure because there is no way to express "function with any arguments" in Swift as a type. The best you can do is wrap your function in a closure with known argument types. There's also no general Closure type that represents any closure.
func invokeIfConditionIsTrue(closure: () -> (), condition: Bool) {
if condition {
closure()
print("executed")
}
}
invokeIfConditionIsTrue(closure: { result = testIntToInt(n) }, condition: true)
But, as you can see, that's not really any better than an if statement. In fact, it's much worse.
Another possibility is to define a function that returns a function, but it still needs to know the argument types.
func invokeIfConditionIsTrue(closure: (Int) -> Int, condition: Bool) -> (Int) -> Int?
{
if condition {
return closure
}
else
{
return { _ in 0 } // A dummy function
}
}
invokeConditionIfTrue(closure: testIntToInt, condition: true)(n)
After some haggling and searching for syntax (I wasn't good in FP, as I mentioned in the beginning), I was able to compile and run the below solution in my XCode 14.2 playground.
My desired function:
func executeIfCondition(function: (#escaping (Any...) -> Any), condition: Bool) {
if condition {
function()
}
}
This was supposed to replace following types of calls across my codebase:
if condition {
function()
}
Test functions whom I want to invoke, using executeIfCondition if condition = true.
func printStringAndReturnInt(i: Int, s: String) -> Int {
print(s)
return i
}
func printInt(i: Int) -> Void {
print("\(i)")
}
func printArray(arr: [Int]) -> Void {
arr.forEach({ print("\($0)") })
}
struct Struct1 {
var value1: Int
var value2: Int
}
func printStruct(t: Struct1) {
print("Struct1: \(t.value1) - \(t.value2)")
}
class Class1 {
var value1: Double = 100.0
var value2: Double = 200.0
}
func printClass(c: Class1) {
print("Class1: \(c.value1) - \(c.value2)")
}
Example Usage:
Instead of:
if (true) {
printStringAndReturnInt(i: 5, s: "Wow!")
}
I will now use:
executeIfCondition(function: { _ in printStringAndReturnInt(i: 5, s: "Wow!") }, condition: true)
The rest:
executeIfCondition(function: { _ in printInt(i: 61) }, condition: false)
executeIfCondition(function: { _ in printArray(arr:[9,10,11,12]) }, condition: true)
executeIfCondition(function: { _ in printStruct(t: Struct1(value1: 100, value2: 200)) }, condition: true)
executeIfCondition(function: { _ in printClass(c: Class1()) }, condition: true)
This isn't exhaustive still, but enough for a start.

How to add filter(_:) method to generic structure in Swift?

I want to add a filter(_:) method to Pyramida structure. It should take a single argument, a closure that: takes an Element and returns a Bool, and return a new Pyramida that contains any elements for which the closure returns true, e.g. values higher than 10.
When I used the same code as per (within exercise) already existent func map also for func filter, its implementation prints out just [false, false, true], however not the values above 10.
Also tried to adjust the func filter as per syntax stated within Developer Documentation, however did not manage it further, too many errors.
struct Pyramida<Element> {
var items = [Element]()
mutating func push(_ newItem: Element) {
items.append(newItem)
}
mutating func pop() -> Element? {
guard !items.isEmpty else {return nil}
return items.removeLast()
}
func map<U>(_ txform: (Element) -> U) -> Pyramida<U> {
var mappedItems = [U]()
for item in items {
mappedItems.append(txform(item))
}
return Pyramida<U>(items: mappedItems)
}
func filter(_ isIncluded: (Element) -> Bool) -> Pyramida<[Int]> {
var filteredItems = [Int]()
for item in items {
if item > 10 {
filteredItems.append(filteredItems(item))
return Pyramida(items: filteredItems)
}
}
}
}
var ints = Pyramida<Int>()
ints.push(2)
ints.push(4)
ints.push(11)
var tripled = ints.map{ 3 * $0 }
print(String(describing: tripled.items))
var aboveTen = ints.filter{ 10 < $0} // code func map<U> for filter<U>
print(String(describing: aboveTen.items))
you have to add this method and if the isIncluded is true you have to append the new element in your array.
func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> Pyramida<Element> {
var newElements: [Element] = []
for number in items where try isIncluded(number) {
newElements.append(number)
}
return Pyramida(items: newElements)
}
and you also can use this.
public func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> Pyramida <Element>{
return Pyramida(items: try items.filter(isIncluded))
}

How to check if a value in a dictionary has duplicates?

The algorithm below checks to see if an array has at least two or more duplicates. It uses a dictionary to store the occurrences; the time complexity is linear because it has to traverse the dictionary to see if a key occurs twice. In swift, how can I look up a value to see if it occurs more than twice in constant time ?
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
frequencyTable[num] = (frequencyTable[num] ?? 0 ) + 1
}
for value in frequencyTable.values{
if value >= 2 {
return true
}
}
return false
}
containsDuplicate([1,1,2,3,3,3,3,4])
The second loop is not necessary if the first loop checks if the current element has already been inserted before, and returns from the function in that case:
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
if frequencyTable[num] != nil {
return true
}
frequencyTable[num] = 1
}
return false
}
Then it becomes apparent that we don't need a dictionary, a set is sufficient:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if seen.contains(num) {
return true
}
seen.insert(num)
}
return false
}
This can be further simplified: The “insert and check if element was already present” operation can be done in a single call:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if !seen.insert(num).inserted {
return true
}
}
return false
}
This is similar to the solution from this answer
return nums.count != Set(nums).count
but possibly more efficient: The function returns immediately when a duplicate element has been detected.
Finally we can make the function generic, so that it works with all arrays of a hashable type:
func containsDuplicate<T: Hashable>(_ array: [T]) -> Bool {
var seen = Set<T>()
for element in array {
if !seen.insert(element).inserted {
return true
}
}
return false
}
Example:
print(containsDuplicate([1,1,2,3,3,3,3,4])) // true
print(containsDuplicate(["A", "X"])) // false
Or as an extension for arbitrary collections of a hashable type:
extension Collection where Element: Hashable {
func containsDuplicate() -> Bool {
var seen = Set<Element>()
for element in self {
if !seen.insert(element).inserted {
return true
}
}
return false
}
}
print([1,1,2,3,3,3,3,4].containsDuplicate())
print(["A", "X"].containsDuplicate())
You just want to know if it has duplicate, you can use use set and compare the length.
func containsDuplicate(_ nums: [Int]) -> Bool {
return Set(nums).count != nums.count
}
like this examples, because the set remove the duplicate values.

Does Swift have a function similar to numpy.diff that calculates the difference between adjacent elements of an array

I'm trying to convert some Python code to Swift and wondering if there is an existing function to calculate the difference between successive elements in a Swift array. For example:
diff([1,3,5,6,10]) would return [2,2,1,4]
No, but it could be very easily implemented:
let a = [1, 3, 5, 6, 10]
zip(a.dropFirst(), a).map(-) // => [2, 2, 1, 4]
It's simple enough that it's probably not worth wrapping into a function, but if you insist:
extension Collection where Element: Numeric {
func diff() -> [Element] {
return zip(self.dropFirst(), self).map(-)
}
}
[1, 3, 5, 6, 10].diff() // => [2, 2, 1, 4]
If you need the result to be lazily evaluated, you can do this:
extension Collection where Element: Numeric {
func diff() -> AnyCollection<Element> {
return AnyCollection(zip(self.dropFirst(), self).lazy.map(-))
}
}
You can use reduce(into:) combined with dropfirst to achieve what you want:
extension Collection where Element: SignedNumeric {
func diff() -> [Element] {
guard var last = first else { return [] }
return dropFirst().reduce(into: []) {
$0.append($1 - last)
last = $1
}
}
}
Another option is to use map and defer:
extension Collection where Element: SignedNumeric {
func diff() -> [Element] {
guard var last = first else { return [] }
return dropFirst().map { element in
defer { last = element }
return element - last
}
}
}
let arr = [1,3,5,6,10]
print(arr.diff()) // "[2, 2, 1, 4]\n"
There's no built in function for this, but you can easily implement it recursively. Thanks for the HeadTail extension for #Alexander.
extension Array {
func headTail<ReturnType>(_ closure: (Element?, [Element]) -> ReturnType) -> ReturnType {
return closure(self.first, Array(self.dropFirst()))
}
}
extension Array where Element == Int {
func diff() -> [Int] {
return self.headTail { head, tail in
guard let head = head, let next = tail.first else { return [] } //base case, empty list
return [next - head] + tail.diff()
}
}
}

Is there a stable sort that works with partial orders in the standard library? [duplicate]

I've been using the sort() function but it mixes up the relative order.
This is how my code looks.
recipes.sort { $0.skill.value <= $1.skill.value }
Swift API says that:
The sorting algorithm is not stable. A nonstable sort may change the
relative order of elements that compare equal.
How can I change this so that the relative order stays the same as before?
The implementation below just work like the sorted method in the standard library, without additional limit.
extension RandomAccessCollection {
/// return a sorted collection
/// this use a stable sort algorithm
///
/// - Parameter areInIncreasingOrder: return nil when two element are equal
/// - Returns: the sorted collection
public func stableSorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] {
let sorted = try enumerated().sorted { (one, another) -> Bool in
if try areInIncreasingOrder(one.element, another.element) {
return true
} else {
return one.offset < another.offset
}
}
return sorted.map { $0.element }
}
}
A stable sort needs to preserve the original order. So we give every element a weight of order besides its value, the index, then the original sort method will just work, as there will never be 2 equal elements.
I appreciate the elegance of leavez's answer. I adapted it to have the same signature as Sequence.sorted(by:):
extension Sequence {
func stableSorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool)
rethrows -> [Element]
{
return try enumerated()
.sorted { a, b -> Bool in
try areInIncreasingOrder(a.element, b.element) ||
(a.offset < b.offset && !areInIncreasingOrder(b.element, a.element))
}
.map { $0.element }
}
}
let sortedArray = (recipes as NSArray).sortedArray(options: .stable, usingComparator: { (lhs, rhs) -> ComparisonResult in
let lhs = (lhs as! Recipe)
let rhs = (rhs as! Recipe)
if lhs.skill.value == rhs.skill.value {
return ComparisonResult.orderedSame
} else if lhs.skill.value < rhs.skill.value {
return ComparisonResult.orderedAscending
} else {
return ComparisonResult.orderedDescending
}
})
Took from here: https://medium.com/#cocotutch/a-swift-sorting-problem-e0ebfc4e46d4
In Swift 5 sort() uses stable implementation and soon it will become officially guaranted to be stable.
From Swift forums:
...
On the other hand, the actual implementation calls
/// Sorts the elements of this buffer according to `areInIncreasingOrder`,
/// using a stable, adaptive merge sort.
///
/// The adaptive algorithm used is Timsort, modified to perform a straight
/// merge of the elements using a temporary buffer.
#inlinable
public mutating func _stableSortImpl(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows { ... }
And
If I recall, sort() is currently stable, but it is not yet guaranteed
to be stable (meaning, the fact that it is stable is currently an
implementation detail, and a future version of Swift could ship an
unstable algorithm instead).
I use this wrapper
extension Array where Element: Comparable, Element: AnyObject {
public func stableSorted() -> [Element] {
let array = self as NSArray
let result = array.sortedArray(options: .stable) { (left, right) -> ComparisonResult in
let left = left as! Element
let right = right as! Element
if left < right {
return ComparisonResult.orderedAscending
}
if left > right {
return ComparisonResult.orderedDescending
}
return ComparisonResult.orderedSame
}
return result as! [Element]
}
public func stableReversed() -> [Element] {
let array = self as NSArray
let result = array.sortedArray(options: .stable) { (left, right) -> ComparisonResult in
let left = left as! Element
let right = right as! Element
if left > right {
return ComparisonResult.orderedAscending
}
if left < right {
return ComparisonResult.orderedDescending
}
return ComparisonResult.orderedSame
}
return result as! [Element]
}
}
I appreciate the elegance of Tom's answer. Harking back to my Perl days I've reworked it to use ComparisonResult and the spaceship (<=>) operator:
extension Sequence {
func sorted(with comparator: (Element, Element) throws -> ComparisonResult) rethrows -> [Element]
{
return try enumerated()
.sorted { (try comparator($0.element, $1.element) || $0.offset <=> $1.offset) == .orderedAscending }
.map { $0.element }
}
}
extension Comparable {
static func <=> (lhs: Self, rhs: Self) -> ComparisonResult {
if lhs < rhs { return .orderedAscending }
if lhs > rhs { return .orderedDescending }
return .orderedSame
}
}
extension ComparisonResult {
static func || (lhs: Self, rhs: #autoclosure () -> Self) -> ComparisonResult {
if lhs == .orderedSame {
return rhs()
}
return lhs
}
}