Skip to content

Commit 55c110a

Browse files
cleitonmarxCleiton Marques Souza
and
Cleiton Marques Souza
authored
Adds DefaultIfEmpty function (#95)
Co-authored-by: Cleiton Marques Souza <[email protected]>
1 parent 7a0b206 commit 55c110a

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

defaultifempty.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package linq
2+
3+
// DefaultIfEmpty returns the elements of the specified sequence
4+
// if the sequence is empty.
5+
func (q Query) DefaultIfEmpty(defaultValue interface{}) Query {
6+
return Query{
7+
Iterate: func() Iterator {
8+
next := q.Iterate()
9+
state := 1
10+
11+
return func() (item interface{}, ok bool) {
12+
switch state {
13+
case 1:
14+
item, ok = next()
15+
if ok {
16+
state = 2
17+
} else {
18+
item = defaultValue
19+
ok = true
20+
state = -1
21+
}
22+
return
23+
case 2:
24+
for item, ok = next(); ok; item, ok = next() {
25+
return
26+
}
27+
return
28+
}
29+
return
30+
}
31+
},
32+
}
33+
}

defaultifempty_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package linq
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestDefaultIfEmpty(t *testing.T) {
8+
defaultValue := 0
9+
tests := []struct {
10+
input []interface{}
11+
want []interface{}
12+
}{
13+
{[]interface{}{}, []interface{}{defaultValue}},
14+
{[]interface{}{1, 2, 3, 4, 5}, []interface{}{1, 2, 3, 4, 5}},
15+
}
16+
17+
for _, test := range tests {
18+
q := From(test.input).DefaultIfEmpty(defaultValue)
19+
20+
if !validateQuery(q, test.want) {
21+
t.Errorf("From(%v).DefaultIfEmpty(%v)=%v expected %v", test.input, defaultValue, toSlice(q), test.want)
22+
}
23+
}
24+
25+
}

example_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,76 @@ func ExampleQuery_CountWith() {
375375
// 6
376376
}
377377

378+
// The following example demonstrates how to use the DefaultIfEmpty
379+
// method on the results of a group join to perform a left outer join.
380+
//
381+
// The first step in producing a left outer join of two collections is to perform
382+
// an inner join by using a group join. In this example, the list of Person objects
383+
// is inner-joined to the list of Pet objects based on a Person object that matches Pet.Owner.
384+
//
385+
// The second step is to include each element of the first (left) collection in the
386+
// result set even if that element has no matches in the right collection.
387+
// This is accomplished by calling DefaultIfEmpty on each sequence of matching
388+
// elements from the group join.
389+
// In this example, DefaultIfEmpty is called on each sequence of matching Pet elements.
390+
// The method returns a collection that contains a single, default value if the sequence
391+
// of matching Pet elements is empty for any Person element, thereby ensuring that each
392+
// Person element is represented in the result collection.
393+
func ExampleQuery_DefaultIfEmpty() {
394+
type Person struct {
395+
FirstName string
396+
LastName string
397+
}
398+
399+
type Pet struct {
400+
Name string
401+
Owner Person
402+
}
403+
404+
magnus := Person{FirstName: "Magnus", LastName: "Hedlund"}
405+
terry := Person{FirstName: "Terry", LastName: "Adams"}
406+
charlotte := Person{FirstName: "Charlotte", LastName: "Weiss"}
407+
arlene := Person{FirstName: "Arlene", LastName: "Huff"}
408+
409+
barley := Pet{Name: "Barley", Owner: terry}
410+
boots := Pet{Name: "Boots", Owner: terry}
411+
whiskers := Pet{Name: "Whiskers", Owner: charlotte}
412+
bluemoon := Pet{Name: "Blue Moon", Owner: terry}
413+
daisy := Pet{Name: "Daisy", Owner: magnus}
414+
415+
// Create two lists.
416+
people := []Person{magnus, terry, charlotte, arlene}
417+
pets := []Pet{barley, boots, whiskers, bluemoon, daisy}
418+
419+
results := []string{}
420+
From(people).
421+
GroupJoinT(
422+
From(pets),
423+
func(person Person) Person { return person },
424+
func(pet Pet) Person { return pet.Owner },
425+
func(person Person, pets []Pet) Group { return Group{Key: person, Group: From(pets).Results()} },
426+
).
427+
SelectManyByT(
428+
func(g Group) Query { return From(g.Group).DefaultIfEmpty(Pet{}) },
429+
func(pet Pet, group Group) string {
430+
return fmt.Sprintf("%s: %s", group.Key.(Person).FirstName, pet.Name)
431+
},
432+
).
433+
ToSlice(&results)
434+
435+
for _, s := range results {
436+
fmt.Println(s)
437+
}
438+
// Output:
439+
// Magnus: Daisy
440+
// Terry: Barley
441+
// Terry: Boots
442+
// Terry: Blue Moon
443+
// Charlotte: Whiskers
444+
// Arlene:
445+
446+
}
447+
378448
//The following code example demonstrates how to use Distinct
379449
//to return distinct elements from a slice of integers.
380450
func ExampleQuery_Distinct() {

0 commit comments

Comments
 (0)