• Stars
    star
    724
  • Rank 60,422 (Top 2 %)
  • Language
    Objective-C
  • License
    Other
  • Created over 11 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Brings a Linq-style fluent query API to Objective-C

Linq To Objective-C

Bringing a Linq-style fluent query API to Objective-C.

This project contains a collection of NSArray and NSDictionary methods that allow you to execute queries using a fluent syntax, inspired by Linq. In order to use Linq to Objective-C simply copy the NSArray+LinqExtensions.h, NSArray+LinqExtensions.m, NSDictionary+LinqExtensions.h and NSDictionary+LinqExtensions.m files into your project and import the header within any file where you wish to use the API.

Alternatively, you can include these files via CocoaPods.

As an example of the types of query this API makes possible, let's say you have an array of Person instances, each with a surname property. The following query will create a sorted, comma-separated list of the unique surnames from the array:

LINQSelector surnameSelector = ^id(id person){
    return [person name];
};

LINQAccumulator csvAccumulator = ^id(id item, id aggregate) {
    return [NSString stringWithFormat:@"%@, %@", aggregate, item];
};

NSArray* surnamesList = [[[[people linq_select:surnameSelector]
                                   linq_sort]
                                   linq_distinct]
                                   linq_aggregate:csvAccumulator];

For a detailed discussion of the history of Linq and why I implemented this API, see the related blog post.

Licence

The code within project is made available under the standard MIT licence, see the included licence file.

API Overview

NSArray methods:

NSDictionary methods:

NSArray methods

This section provides a few brief examples of each of the API methods. A number of these examples use an array of Person instances:

interface Person : NSObject

@property (retain, nonatomic) NSString* name;
@property (retain, nonatomic) NSNumber* age;

@end

linq_where

- (NSArray*) linq_where:(LINQCondition)predicate;

Filters a sequence of values based on a predicate.

The following example uses the where method to find people who are 25:

NSArray* peopleWhoAre25 = [input linq_where:^BOOL(id person) {
    return [[person age] isEqualToNumber:@25];
}];

linq_select

- (NSArray*) linq_select:(LINQSelector)transform;

Projects each element of a sequence into a new form. Each element in the array is transformed by a 'selector' into a new form, which is then used to populate the output array.

The following example uses a selector that returns the name of each Person instance. The output will be an array of NSString instances.

NSArray* names = [input linq_select:^id(id person) {
    return [person name];
}];

linq_selectAndStopOnNil

- (NSArray*)linq_selectAndStopOnNil:(LINQSelector)transform;

Projects each element of a sequence into a new form. If the transform returns nil for any of the elements, the projection fails and returns nil.

linq_sort

- (NSArray*) linq_sort;
- (NSArray*) linq_sort:(LINQSelector)keySelector;
- (NSArray*) linq_sortDescending;
- (NSArray*) linq_sortDescending:(LINQSelector)keySelector;

Sorts the elements of an array, either via their 'natural' sort order, or via a keySelector.

As an example of natural sort, the following sorts a collection of NSNumber instances:

NSArray* input = @[@21, @34, @25];
NSArray* sortedInput = [input linq_sort]; // 21, 25, 34

In order to sort an array of Person instances, you can use the key selector:

NSArray* sortedByName = [input linq_sort:^id(id person) {
    return [person name];
}];

The accompanying 'descending' methods simply reverse the sort order:

NSArray* input = @[@21, @34, @25];
NSArray* sortedInput = [input linq_sort]; // 21, 25, 34
NSArray* sortedInput = [input linq_sortDescending]; // 34, 25, 21

linq_sum

- (NSNumber *)linq_sum;

Sums the elements in the array.

linq_ofType

- (NSArray*) linq_ofType:(Class)type;

Filters the elements of an an array based on a specified type.

In the following example a mixed array of NSString and NSNumber instances is filtered to return just the NSString instances:

NSArray* mixed = @[@"foo", @25, @"bar", @33];
NSArray* strings = [mixed linq_ofType:[NSString class]];

linq_selectMany

- (NSArray*) linq_selectMany:(LINQSelector)transform;

Projects each element of a sequence to an NSArray and flattens the resulting sequences into one sequence.

This is an interesting one! This is similar to the select method, however the selector must return an NSArray, with the select-many operation flattening the returned arrays into a single sequence.

Here's a quick example:

NSArray* data = @[@"foo, bar", @"fubar"];

NSArray* components = [data linq_selectMany:^id(id string) {
    return [string componentsSeparatedByString:@", "];
}];

A more useful example might use select-many to return all the order-lines for an array of orders.

linq_distinct

- (NSArray*) linq_distinct;
- (NSArray*) linq_distinct:(LINQSelector)keySelector;

Returns distinct elements from a sequence. This simply takes an array of items, returning an array of the distinct (i.e. unique) values in source order.

The no-arg version of this method uses the default method of comparing the given objects. The version that takes a key-selector allows you to specify the value to use for equality for each item.

Here's an example that returns the distinct values from an array of strings:

NSArray* names = @[@"bill", @"bob", @"bob", @"brian", @"bob"];
NSArray* distinctNames = [names linq_distinct];
// returns bill, bob and brian

Here's a more complex example that uses the key selector to find people instances with distinct ages:

NSArray* peopleWithUniqueAges = [input linq_distinct:^id(id person) {
    return [person age];
}];

linq_aggregate

- (id) linq_aggregate:(LINQAccumulator)accumulator;

Applies an accumulator function over a sequence. This method transforms an array into a single value by applying an accumulator function to each successive element.

Here's an example that creates a comma separated list from an array of strings:

NSArray* names = @[@"bill", @"bob", @"brian"];

id aggregate = [names linq_aggregate:^id(id item, id aggregate) {
    return [NSString stringWithFormat:@"%@, %@", aggregate, item];
}];
// returns "bill, bob, brian"

Here's another example that returns the largest value from an array of numbers:

NSArray* numbers = @[@22, @45, @33];

id biggestNumber = [numbers linq_aggregate:^id(id item, id aggregate) {
    return [item compare:aggregate] == NSOrderedDescending ? item : aggregate;
}];
// returns 45 

linq_firstOrNil

- (id) linq_firstOrNil;
- (id) linq_firstOrNil:(LINQCondition)predicate;

Returns the first element of an array, or nil if the array is empty.

linq_lastOrNil

- (id) linq_lastOrNil;

Returns the last element of an array, or nil if the array is empty

linq_skip

- (NSArray*) linq_skip:(NSUInteger)count;

Returns an array that skips the first 'n' elements of the source array, including the rest.

linq_take

- (NSArray*) linq_take:(NSUInteger)count;

Returns an array that contains the first 'n' elements of the source array.

linq_any

- (BOOL) linq_any:(LINQCondition)condition;

Tests whether any item in the array passes the given condition.

As an example, you can check whether any number in an array is equal to 25:

NSArray* input = @[@25, @44, @36];
BOOL isAnyEqual = [input linq_any:^BOOL(id item) {
        return [item isEqualToNumber:@25];
    }];
// returns YES

linq_all

- (BOOL) linq_all:(LINQCondition)condition;

Tests whether all the items in the array pass the given condition.

As an example, you can check whether all the numbers in an array are equal to 25:

NSArray* input = @[@25, @44, @36];
BOOL areAllEqual = [input linq_all:^BOOL(id item) {
        return [item isEqualToNumber:@25];
    }];
// returns NO

linq_groupBy

- (NSDictionary*) linq_groupBy:(LINQSelector)groupKeySelector;

Groups the items in an array returning a dictionary. The groupKeySelector is applied to each element in the array to determine which group it belongs to.

The returned dictionary has the group values (as returned by the key selector) as its keys, with an NSArray for each value, containing all the items within that group.

As an example, if you wanted to group a number of strings by their first letter, you could do the following:

NSArray* input = @[@"James", @"Jim", @"Bob"];
    
NSDictionary* groupedByFirstLetter = [input linq_groupBy:^id(id name) {
   return [name substringToIndex:1];
}];
// the returned dictionary is as follows:
// {
//     J = ("James", "Jim");
//     B = ("Bob");
// }

linq_toDictionary

- (NSDictionary*) linq_toDictionaryWithKeySelector:(LINQSelector)keySelector;
- (NSDictionary*) linq_toDictionaryWithKeySelector:(LINQSelector)keySelector valueSelector:(LINQSelector)valueSelector;

Transforms the source array into a dictionary by applying the given keySelector and (optional) valueSelector to each item in the array. If you use the toDictionaryWithKeySelector: method, or the toDictionaryWithKeySelector:valueSelector: method with a nil valueSelector, the value for each dictionary item is simply the item from the source array.

As an example, the following code takes an array of names, creating a dictionary where the key is the first letter of each name and the value is the name (in lower case).

NSArray* input = @[@"Frank", @"Jim", @"Bob"];

NSDictionary* dictionary = [input linq_toDictionaryWithKeySelector:^id(id item) {
    return [item substringToIndex:1];
} valueSelector:^id(id item) {
    return [item lowercaseString];
}];

// result:
// (
//    F = frank;
//    J = jim;
//    B = bob;
// )

Whereas in the following there is no value selector, so the strings from the source array are used directly.

NSArray* input = @[@"Frank", @"Jim", @"Bob"];

NSDictionary* dictionary = [input linq_toDictionaryWithKeySelector:^id(id item) {
    return [item substringToIndex:1];
}];

// result:
// (
//    F = Frank;
//    J = Jim;
//    B = Bob;
// )

linq_count

- (NSUInteger) linq_count:(LINQCondition)condition;

Counts the number of elements in an array that pass a given condition.

As an example, you can check how many numbers equal a certain value:

NSArray* input = @[@25, @35, @25];

NSUInteger numbersEqualTo25 = [input linq_count:^BOOL(id item) {
    return [item isEqualToNumber:@25];
}];
// returns 2

linq_concat

- (NSArray*) linq_concat:(NSArray*)array;

Returns an array which is the result of concatonating the given array to the end of this array.

linq_reverse

- (NSArray*) linq_reverse;

Returns an array that has the same elements as the source but in reverse order.

NSDictionary methods

This section provides a few brief examples of each of the API methods.

linq_where

- (NSDictionary*) linq_where:(LINQKeyValueCondition)predicate;

Filters a dictionary based on a predicate.

The following example uses filters a dictionary to remove any keys that are equal to their value.

NSDictionary* result = [input linq_where:^BOOL(id key, id value) {
   return [key isEqual:value];
}];

linq_select

- (NSDictionary*) linq_select:(LINQKeyValueConditionKeyValueSelector)selector;

Projects each key-value pair in a dictionary into a new form. Each key-value pair is transformed by a 'selector' into a new form, which is then used to populate the values of the output dictionary.

The following example takes a dictionary which has string values, returning a new dictionary where each value is the first character of the source string.

NSDictionary* result = [input linq_select:^id(id key, id value) {
    return [value substringToIndex:1];
}];

linq_toArray

- (NSArray*) linq_toArray:(LINQKeyValueSelector)selector;

Projects each key-value pair in a dictionary into a new form, which is used to populate the output array.

The following example takes a dictionary which has string values, returning an array which concatenates the key and value for each item in the dictionary.

NSDictionary* input = @{@"A" : @"Apple", @"B" : @"Banana", @"C" : @"Carrot"};

NSArray* result = [input linq_toArray:^id(id key, id value) {
    return [NSString stringWithFormat:@"%@, %@", key, value];
}];

// result:
// (
//    "A, Apple",
//    "B, Banana",
//    "C, Carrot"
// )

linq_any

- (BOOL) linq_any:(LINQKeyValueCondition)condition;

Tests whether any key-value pair in the dictionary passes the given condition.

As an example, you can check whether value contains the letter 'n':

NSDictionary* input = @{@"a" : @"apple", @"b" : @"banana", @"c" : @"bat"};

BOOL anyValuesHaveTheLetterN = [input linq_any:^BOOL(id key, id value) {
    return [value rangeOfString:@"n"].length != 0;
}];
// returns YES

linq_all

- (BOOL) linq_all:(LINQKeyValueCondition)condition;

Tests whether all the key-value pairs in the dictionary pass the given condition.

As an example, you can check whether all values contains the letter 'a', or use the key component of the condition to see if each value contains the string key:

NSDictionary* input = @{@"a" : @"apple", @"b" : @"banana", @"c" : @"bat"};

BOOL allValuesHaveTheLetterA = [input linq_all:^BOOL(id key, id value) {
    return [value rangeOfString:@"a"].length != 0;
}];
// returns YES

BOOL allValuesContainKey = [input linq_all:^BOOL(id key, id value) {
    return [value rangeOfString:key].length != 0;
}];
// returns NO - the value 'bat' does not contain the letter it is keyed with 'c'

linq_count

- (NSUInteger) linq_count:(LINQKeyValueCondition)condition;

Counts the number of key-value pairs that satisfy the given condition.

The following example counts how many dictionary values contain the key:

NSDictionary* input = @{@"a" : @"apple", @"b" : @"banana", @"c" : @"bat"};


NSUInteger valuesThatContainKey = [input linq_count:^BOOL(id key, id value) {
    return [value rangeOfString:key].length != 0;
}];
// returns 2 - "bat" does not contain the key "c"

linq_merge

- (NSDictionary*) linq_merge:(NSDictionary*)dic;

Merges the contents of this dictionary with the given dictionary. For any duplicates, the value from the source dictionary will be used.

The following example merges a pair of dictionaries

NSDictionary* input = @{@"a" : @"apple", @"b" : @"banana", @"c" : @"cat"};

NSDictionary* result = [input linq_merge:@{@"d" : @"dog", @"e" : @"elephant"}];

// result:
// (
//    a = apple;
//    b = banana;
//    c = cat;
//    d = dog;
//    e = elephant;
// )

More Repositories

1

VCTransitionsLibrary

A collection of iOS7 animation controllers and interaction controllers, providing flip, fold and all kinds of other transitions.
Objective-C
4,554
star
2

applause-button

A zero-configuration medium-style button for adding applause / claps / kudos to web pages and blog posts
JavaScript
414
star
3

ReactiveSwiftFlickrSearch

A Swift implementation of a Flickr-search application that uses MVVM and ReactiveCocoa
Swift
377
star
4

wasm-sudoku-solver

a WebAssembly-powered AR sudoku solver
JavaScript
337
star
5

chasm

A simple compile-to-WebAssembly language
TypeScript
330
star
6

awesome-public-streaming-datasets

A list of free datasets that provide streaming data
280
star
7

ReactNative-PropertyFinder

A property finder application written using React Native
JavaScript
276
star
8

wasm-rust-chip8

A WebAssembly CHIP-8 emulator written with Rust
Rust
251
star
9

langchain-mini

๐Ÿฆœ๏ธ๐Ÿ”— This is a very simple re-implementation of LangChain, in ~100 lines of code
JavaScript
234
star
10

ReactiveTwitterSearch

A ReactiveCocoa 4.0 MVVM example
Swift
215
star
11

iOS-ClearStyle

This project is a gesture-driven iOS to-do list application modelled on the iPhone Clear application.
Objective-C
195
star
12

ffmpeg-wasm-streaming-video-player

An example of using FFmpeg.wasm to perform streaming transcoding within the browser
JavaScript
145
star
13

json-transforms

A recursive, pattern-matching, approach to transforming JSON structures.
JavaScript
133
star
14

CETableViewBinding

Demonstrates a binding helper that makes it easier to bind UITableView instances to ReactiveCocoa ViewModels
Objective-C
120
star
15

d3-wasm-force

A re-implementation of d3-force with WebAssembly.
TypeScript
105
star
16

angular2-todo

A todo list implemented using Angular 2
TypeScript
91
star
17

d3fc-webgl-hathi-explorer

A T-SNE scatter plot implemented using D3FC's WebGL series
JavaScript
89
star
18

ReactiveFlickrSearch

A ReactiveCocoa-MVVM application that searches Flickr
Objective-C
89
star
19

assemblyscript-regex

A regex engine for AssemblyScript
TypeScript
86
star
20

ReactSwift

A prototype implementation of React in Swift
Swift
77
star
21

wasmweekly

Website for the WebAssembly weekly newsletter
HTML
74
star
22

UIKit-Dynamics-Playground

The code to accompany the article published here: http://www.raywenderlich.com/50197/uikit-dynamics-tutorial
Objective-C
68
star
23

wasm-game-of-life

Conway's Game of Life - hand written in WebAssembly
WebAssembly
59
star
24

wasm-mandelbrot

A mandelbrot rendered using a variety of WebAssembly tools (emscripten, AssemblyScript, asm.js, etc ...)
JavaScript
54
star
25

RWReactivePlayground

A project to accompany an article I wrote on ReactiveCocoa, a simple sign-in form.
Objective-C
52
star
26

atari2600-wasm

An Atari 2600 emulator written in AssemblyScript compiled to WebAssembly
JavaScript
51
star
27

yahoo-finance-d3fc

A complex financial chart built with D3 and d3fc
JavaScript
48
star
28

RWTwitterInstant

A project to accompany an article I wrote on ReactiveCocoa, a twitter search application
Objective-C
43
star
29

mandelbrot-threaded-webassembly

A simple demonstration of WebAssembly threads
WebAssembly
41
star
30

applause-button-server

The server-side component for the applause button
JavaScript
41
star
31

angular2-goldilocks-seed

A seed project for Angular 2.0 / TypeScript development
JavaScript
40
star
32

redux-reducer-array

An app that demonstrates a method for applying redux reducers to arrays of items
JavaScript
36
star
33

rust-webassembly-serverless

An AWS lambda function written in Rust using WebAssembly
Rust
30
star
34

ReactiveSwiftLondon

A Twitter Search app with Sentiment Analysis, powered by ReactiveCocoa
Swift
27
star
35

SwiftFunctionalLife

An implementation of Conway's Game of Life using functional concepts in Swift
Swift
27
star
36

CERangeSlider

A range slider control for iOS
27
star
37

SwiftReactivePlayground

A project that accompanies my talk, ReactiveCocoa made Simple with Swift
Swift
27
star
38

wasm-faas

A simple WebAssembly-powered serverless platform written in Rust.
Rust
26
star
39

running-report-card

Creates a narrative report card from Strava user's running data
HTML
25
star
40

assemblyscript-temporal

An implementation of TC39 temporal for AssemblyScript
TypeScript
23
star
41

WP7-ClearStyle

This project is a gesture-driven Windows Phone to-do list application modelled on the iPhone Clear application.
C#
20
star
42

SimulatorEnhancements

Enhances the iOS simulator, providing accelerometer and geolocation data
Objective-C
20
star
43

SimulatorEnhancements-Server

Enhances the iOS simulator, providing accelerometer and geolocation data.
JavaScript
17
star
44

Avalon

A prototype binding framework for iOS - to support the MVVM pattern
Swift
16
star
45

SwiftMandelbrot

A project that shows how the simple task of computing a Mandelbrot set can be split up across multiple threads
Swift
14
star
46

jekyll-pagination-infinite-scroll

A demonstration of Jekyll pagination with infinite scroling
CSS
13
star
47

Knockout-jQueryMobile

A simple example of integration between jQueryMobile with KnockoutJS
JavaScript
8
star
48

gifbot

A GitHub bot that serves up animated GIFs on demand!
JavaScript
8
star
49

d3fc-label-layout

A D3 layout that places labels avoiding overlaps using either a greedy or simulated annealing strategy
JavaScript
8
star
50

time-travel-trader

An app that demonstrates the use of Hot Module Reload and Time Travel within the context of a trading platform
TypeScript
7
star
51

timezone-viz

An interactive timezone visualisation
JavaScript
7
star
52

BindingWithBond

An example app that demonstrates the Swift Bond binding framework
Swift
7
star
53

wasm-interference

A hand-coded WebAssembly interference pattern thingy
WebAssembly
7
star
54

iOS-Reversi

An iPad Reversi game that I am writing for a RayWenderlich tutorial
Objective-C
6
star
55

d3fc-financial-chart

Illustrates the patterns you should consider when creating high performance complex charts
WebAssembly
6
star
56

grunt-mdspell

A grunt task that spell checks markdown files
JavaScript
6
star
57

mondo-expenses-app

An example Mondo app that obtains transactions tagged with #expenses
HTML
5
star
58

ReversiEight

A Windows 8 Reversi board game
C#
5
star
59

assemblyscript-temporal-tz

An implementation of time-zone aware TC39 temporal classes for AssemblyScript
TypeScript
5
star
60

PropertyFinder-HTML5

Property Finder is an HTML5-based cross-platform mobile application for Windows Phone and iPhone.
JavaScript
5
star
61

d3fc-github-viz

A visualisation of github repository statistics
JavaScript
4
star
62

awesome-lists-bot

A bot that runs various checks against 'awesome list' projects
JavaScript
4
star
63

finwasm-smart-contract

A smart contract demonstration that allows sign-up for a fictitious meetup event
HTML
4
star
64

openfin-tabbed-interface

A demo app that shows how to create a Chrome-style tear-out desktop HTML5 interface with OpenFin.
CSS
4
star
65

perspective-rs

A prototype implementation of Perspective in Rust
Rust
4
star
66

tiny-ssg

A tiny static site generator that can be used to replace Assemble, etc ...
JavaScript
4
star
67

wasm-lang-inference

Exploring techniques that may allow us to infer the language used to write WebAssembly modules
Rust
4
star
68

WP8-MapGestures

An enhanced set of multi-touch gestures for the Windows Phone 8 map control
C#
3
star
69

colineberhardt.github.com

HTML
3
star
70

awesome-stars

โ˜…โ˜…โ˜… Adds the star counts to awesome lists โ˜…โ˜…โ˜…
JavaScript
3
star
71

d3fc-technical-indicator

Components for calculating technical indicators on data series
JavaScript
2
star
72

rollup-plugin-webassembly

A rollup plugin that inlines (base64 encoded) and imports WebAssembly modules
JavaScript
2
star
73

Monoliths-To-Components-With-D3

From monoliths to components with D3 - A presentation about building re-useable charting components with d3fc
JavaScript
2
star
74

d3fc-financial-feed

An API for fetching financial time-series data from different sources including Quandl and Coinbase
JavaScript
2
star
75

html5-revolution

An impress.js powered presentation about the rise of HTML5 and death of plugins
1
star
76

ServerlessNodeHttpPost

A simple servless template for lambdas exposed via the gateway using HTTP POST
JavaScript
1
star
77

natter

JavaScript
1
star
78

d3fc-webgl-example

An example of the D3FC with WebGL rendering
JavaScript
1
star
79

PropertyCross-Site

Website for PropertyCross
CSS
1
star
80

Xamarin-cross-platform-charting

Demonstration of using ShinobiCharts Xamarin bindings to create a cross-platform app for data visualisation
C#
1
star
81

d3fc-brush

Adapts the D3 brush, making it easier to create data-driven brushed charts.
JavaScript
1
star