25

I know that Swift is relatively new yet, but I would like to know if Swift have anything like LINQ in C#?

With LINQ I mean all the excellent tools like Standard Query Operators, Anonymous types, Object Initializer, etc.

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
  • 2
    Two LINQ for Swift open source projects, and a good ManiacDev article about SINQ. https://github.com/mythz/swift-linq-examples https://github.com/slazyk/SINQ https://maniacdev.com/2015/02/open-source-swift-library-providing-linq-inspired-syntax-for-using-sequences-and-collections – johnrubythecat Apr 28 '15 at 12:06

3 Answers3

59

Swift incorporates several of the features that are bundled together in .net as LINQ, though possibly not in quite an out-of-the-box sense.

Anonymous types are quite close to tuples with named values in Swift.

In C#:

   var person = new { firstName = "John", lastName = "Smith" };
   Console.WriteLine(person.lastName);

Output: Smith

In Swift:

var person = (firstName: "John", lastName: "Smith")
person.firstName = "Fred"
print(person.lastName)

Output: Smith

LINQ queries are of course very powerful/expressive, but you can replicate a large portion of what they do using map, filter and reduce in Swift. With lazy, you can get the same functionality where you create an object that can be looped over ahead of time, and only evaluate it when the looping actually happens:

In C#:

var results =
 SomeCollection
    .Where(c => c.SomeProperty < 10)
    .Select(c => new {c.SomeProperty, c.OtherProperty});

foreach (var result in results)
{
    Console.WriteLine(result.ToString());
}

In Swift:

// just so you can try this out in a playground...
let someCollection = [(someProperty: 8, otherProperty: "hello", thirdProperty: "foo")]

let results =
  someCollection.lazy
    .filter { c in c.someProperty < 10 }
    // or instead of "c in", you can use $0:
    .map { ($0.someProperty, $0.otherProperty) }

for result in results {
    print(result)
}

Swift generics make writing operations similar to existing LINQ functionality quite straightforward. For example, from the LINQ wikipedia article:

Count The Count operator counts the number of elements in the given collection. An overload taking a predicate, counts the number of elements matching the predicate.

Could be written in Swift like this (2.0 protocol extension syntax):

extension SequenceType {
    // overload for count that takes a predicate
    func count(match: Generator.Element -> Bool) -> Int {
        return reduce(0) { n, elem in match(elem) ? n + 1 : n }
    }
}

// example usage
let isEven = { $0 % 2 == 0 }

[1,1,2,4].count(isEven)  // returns 2

You could also overload it to take a particular element to count if the element conforms to Equatable:

extension SequenceType where Generator.Element: Equatable {
    // overload for count that takes a predicate
    func count(element: Generator.Element) -> Int {
        return count { $0 == element }
    }
}

[1,1,2,4].count(1)

Structs by default have object-initializer-like syntax:

struct Person { let name: String; let age: Int; }

let person = Person(name: "Fred Bloggs", age: 37)

and via ArrayLiteralConvertible, any collection type can have similar syntax to collection initializer syntax:

let list: MyListImplementation = [1,2,3,4]
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • Agreed. That is the optimal answer @AirspeedVelocity – apollosoftware.org Apr 16 '15 at 10:18
  • 1
    What a great answer, it was exactly the kind of answer I hoped there'd be. – JJP Mar 25 '16 at 13:04
  • 1
    Good answer, but doesn't address the limitations. Specifically, the most valuable asset of linq is the ability to implement your own query providers, which isn't possible in swift (at least not easily) because run time interpretation of code isn't supported first class. – Ian Newson Aug 26 '16 at 05:16
  • 1
    It is all very good, however by far the most valuable feature of Linq is to be able to execute on the DB side. 3rd party developers developed integration to the most well knows databases so var a = entity.Where(x=> x.Age > 21) is translated into Sql queries and are executed remotely. Without this the usefulness on Linq would be very low. – user2555515 Sep 13 '21 at 22:32
3

See also:

https://github.com/slazyk/SINQ

Even though it is a bit outdated since Swift now includes native lazy() functionality.

Teejay
  • 7,210
  • 10
  • 45
  • 76
2

I'd personally use CoreData or NSPredicate for some LINQ like functionality. It meshes with Swift I'm sure. I've only used it in Objective-C, but I've seen articles people implementing it with Swift.

http://nshipster.com/nspredicate/

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
apollosoftware.org
  • 12,161
  • 4
  • 48
  • 69