Skip to content
This repository has been archived by the owner on Mar 29, 2018. It is now read-only.

Commit

Permalink
groupBy, difference (Dictionary)
Browse files Browse the repository at this point in the history
- Array (groupBy)
- Dictionary (groupBy, difference)
  • Loading branch information
pNre committed Jun 7, 2014
1 parent 39d89b9 commit 10c9580
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 40 deletions.
Binary file not shown.
39 changes: 28 additions & 11 deletions ExSwift/Array.swift
Expand Up @@ -358,26 +358,43 @@ extension Array {
*/
func groupBy <U> (groupingFunction group: (T) -> (U)) -> Dictionary<U, Array<T>> {

var result = Dictionary<U, Array<T>>();
var result = Dictionary<U, T[]>();

for item in self {

let groupKey = group(item)
var array: Array<T>? = nil
var array: T[]? = nil

// This is the first object for groupKey
if !result.has(groupKey) {
array = Array<T>()
result[groupKey] = [item]
} else {
array = result[groupKey]
result[groupKey] = (result[groupKey]! as T[]) + [item]
}

}

return result

}

/**
* Similar to groupBy, but instead of returning a list of values, returns the number of values for each group
* @param groupingFunction
* @return Grouped dictionary
*/
func countBy <U> (groupingFunction group: (T) -> (U)) -> Dictionary<U, Int> {

var result = Dictionary<U, Int>();

for item in self {
let groupKey = group(item)

var finalArray = array!

finalArray.push(item)

result[groupKey] = finalArray

if !result.has(groupKey) {
result[groupKey] = 1
} else {
result[groupKey] = result[groupKey]! + 1
}
}

return result
Expand All @@ -401,7 +418,7 @@ extension Array {
/**
* self.reduce from right to left
*/
func reduceRight <U>(initial: U, combine: (U, Element) -> U) -> U {
func reduceRight <U> (initial: U, combine: (U, Element) -> U) -> U {
return self.reverse().reduce(initial, combine: combine)
}

Expand Down
79 changes: 70 additions & 9 deletions ExSwift/Dictionary.swift
Expand Up @@ -10,7 +10,39 @@ import Foundation
import Swift

extension Dictionary {


/**
* Computes the difference between self and the input dictionaries
* @param dictionaries Dictionaries to subtract
* @return Difference between self and the input dictionaries
*/
func difference <V: Equatable> (dictionaries: Dictionary<KeyType, V>...) -> Dictionary<KeyType, V>? {

// Checks if self's elements are compatbile with V
if !self.all( { return $1 is V } ) {
return nil
}

var result = Dictionary<KeyType, V>()

// Cast everything to V
for (key, value) in self {
result[key] = value as? V
}

// Difference
for dictionary in dictionaries {
for (key, value) in dictionary {
if result.has(key) && result[key] == value {
result.removeValueForKey(key)
}
}
}

return result

}

/**
* Checks if the specified key exists in the dictionary
* @param key Key to check
Expand Down Expand Up @@ -127,25 +159,45 @@ extension Dictionary {
*/
func groupBy <T> (groupingFunction group: (KeyType, ValueType) -> (T)) -> Dictionary<T, Array<ValueType>> {

var result = Dictionary<T, Array<ValueType>>();
var result = Dictionary<T, ValueType[]>();

for (key, value) in self {

let groupKey = group(key, value)
var array: Array<ValueType>? = nil
var array: ValueType[]? = nil

// This is the first object for groupKey
if !result.has(groupKey) {
array = Array<ValueType>()
result[groupKey] = [value]
} else {
array = result[groupKey]
result[groupKey] = result[groupKey]! + [value]
}

var finalArray = array!

finalArray.push(value)
}

return result

}

/**
* Similar to groupBy, but instead of returning a list of values, returns the number of values for each group
* @param groupingFunction
* @return Grouped dictionary
*/
func countBy <T> (groupingFunction group: (KeyType, ValueType) -> (T)) -> Dictionary<T, Int> {

var result = Dictionary<T, Int>();

for (key, value) in self {

result[groupKey] = finalArray
let groupKey = group(key, value)

// This is the first object for groupKey
if !result.has(groupKey) {
result[groupKey] = 1
} else {
result[groupKey] = result[groupKey]! + 1
}

}

Expand Down Expand Up @@ -206,3 +258,12 @@ extension Dictionary {
}

}

/**
* Shorthand for the difference
*/

@infix func - <K, V: Equatable> (first: Dictionary<K, V>, second: Dictionary<K, V>) -> Dictionary<K, V> {
return first.difference(second)!
}

6 changes: 3 additions & 3 deletions ExSwift/Range.swift
Expand Up @@ -15,7 +15,7 @@ extension Range {
* @param call Function to call
*/
func times (call: () -> ()) {
self.each { (current: T) -> () in
each { (current: T) -> () in
call()
}
}
Expand All @@ -25,9 +25,9 @@ extension Range {
* @param call Function to call
*/
func times (call: (T) -> ()) {
self.each (call)
each (call)
}

/**
* Calls a function foreach element in the range
* @param call Function to call
Expand Down
30 changes: 18 additions & 12 deletions ExSwiftTests/ExSwiftArrayTests.swift
Expand Up @@ -187,6 +187,15 @@ class ExtensionsArrayTests: XCTestCase {
XCTAssert(Array(group[true]!) == [4, 5])
XCTAssert(Array(group[false]!) == [1, 2, 3])
}

func testCountBy() {
let group = array.countBy(groupingFunction: {
(value: Int) -> Bool in
return value > 3
})

XCTAssert(group == [true: 2, false: 3])
}

func testReduceRight () {
let list = [[0, 1], [2, 3], [4, 5]];
Expand All @@ -197,20 +206,17 @@ class ExtensionsArrayTests: XCTestCase {
func testImplode () {
XCTAssert(["A", "B", "C"].implode("A") == "AABAC")
}
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD

func testPluck () {

let values = [
["Name": "Bob", "Score": 6],
["Name": "Tim", "Score": 8]
]

let result = values.pluck("Score") as Int[]

println(result)

}
=======
=======
>>>>>>> FETCH_HEAD
=======
>>>>>>> FETCH_HEAD

>>>>>>> FETCH_HEAD
/*
func testPerformanceExample() {
// This is an example of a performance test case.
Expand Down
24 changes: 22 additions & 2 deletions ExSwiftTests/ExSwiftDictionaryTests.swift
Expand Up @@ -77,7 +77,22 @@ class ExSwiftDictionaryTests: XCTestCase {
XCTAssert(Array(g[true]!) == [2, 4])
XCTAssert(Array(g[false]!) == [5])
}


func testCountBy() {
let group = [
"A": 2,
"B": 4,
"C": 5
]

let g = group.countBy(groupingFunction: {
(key: String, value: Int) -> Bool in
return (value % 2 == 0)
})

XCTAssert(g == [false: 1, true: 2])
}

func testAny() {
let any = dictionary.any {
(key: String, value: Int) -> Bool in
Expand All @@ -97,15 +112,20 @@ class ExSwiftDictionaryTests: XCTestCase {
}

func testReduce () {

let reduced = dictionary.reduce(Dictionary<Int, String>(), {
(var initial: Dictionary<Int, String>, couple: (String, Int)) in
initial.updateValue(couple.0, forKey: couple.1)
return initial
})

XCTAssert(reduced == [2: "B", 3: "C", 1: "A"])
}

func testDifference () {
let dictionary1 = [ "A": 1, "B": 2, "C": 3 ]
let dictionary2 = [ "A": 1 ]

XCTAssert(dictionary1 - dictionary2 == ["C": 3, "B": 2])
}

}
12 changes: 12 additions & 0 deletions Examples/Array.md
Expand Up @@ -30,6 +30,7 @@
- [`shift`](#shift)
- [`unshift`](#unshift)
- [`groupBy`](#groupby)
- [`countBy`](#countby)
- [`reduceRight`](#reduceright)
- [`implode`](#implode)
- [Class Methods](#class-methods)
Expand Down Expand Up @@ -256,13 +257,24 @@ println(array)

##### `groupBy` #####
```
let array = array = [1, 2, 3, 4, 5]
let group = array.groupBy(groupingFunction: {
(value: Int) -> Bool in
return value > 3
})
// → [true: [5, 6], false: [1, 2, 3]]
```

##### `countBy` #####
```
let array = array = [1, 2, 3, 4, 5]
let group = array.countBy(groupingFunction: {
(value: Int) -> Bool in
return value > 3
})
// → [true: 2, false: 3]
```

##### `reduceRight` #####
```
let list = [[0, 1], [2, 3], [4, 5]];
Expand Down
31 changes: 31 additions & 0 deletions Examples/Dictionary.md
Expand Up @@ -3,6 +3,7 @@

- [Dictionary](#dictionary)
- [Instance Methods](#instance-methods)
- [`difference`](#difference)
- [`has`](#has)
- [`isEmpty`](#isempty)
- [`map`](#map)
Expand All @@ -12,12 +13,25 @@
- [`merge`](#merge)
- [`shift`](#shift)
- [`groupBy`](#groupby)
- [`countBy`](#countby)
- [`all`](#all)
- [`any`](#any)
- [`reduce`](#reduce)

### Instance Methods ###

#### `difference` ####
```swift
let dictionary1 = [ "A": 1, "B": 2, "C": 3 ]
let dictionary2 = [ "A": 1 ]

let diff1 = dictionary1.difference(dictionary2)
// → [C: 3, B: 2]

let diff2 = dictionary1 - dictionary2
// → [C: 3, B: 2]
```

#### `has` ####
```swift
let dictionary = [ "A": 1, "B": 2, "C": 3 ]
Expand Down Expand Up @@ -94,6 +108,23 @@ let g = group.groupBy(groupingFunction: {
// → [false: [5], true: [2, 4]]
```

#### `countBy`####

```swift
let group = [
"A": 2,
"B": 4,
"C": 5
]

let g = group.countBy(groupingFunction: {
(key: String, value: Int) -> Bool in
return (value % 2 == 0)
})

// → [false: 1, true: 2]
```

#### `any` ####
```swift
let dictionary = [ "A": 1, "B": 2, "C": 3 ]
Expand Down

0 comments on commit 10c9580

Please sign in to comment.