GithubHelp home page GithubHelp logo

ahmetb / go-linq Goto Github PK

View Code? Open in Web Editor NEW
3.4K 81.0 224.0 936 KB

.NET LINQ capabilities in Go

Home Page: https://godoc.org/github.com/ahmetb/go-linq

License: Apache License 2.0

Go 100.00%
go linq generic-functions

go-linq's Introduction

go-linq GoDoc Build Status Coverage Status Go Report Card

A powerful language integrated query (LINQ) library for Go.

  • Written in vanilla Go, no dependencies!
  • Complete lazy evaluation with iterator pattern
  • Safe for concurrent use
  • Supports generic functions to make your code cleaner and free of type assertions
  • Supports arrays, slices, maps, strings, channels and custom collections

Installation

When used with Go modules, use the following import path:

go get github.com/ahmetb/go-linq/v3

Older versions of Go using different dependency management tools can use the following import path to prevent breaking API changes:

go get gopkg.in/ahmetb/go-linq.v3

Quickstart

Usage is as easy as chaining methods like:

From(slice) .Where(predicate) .Select(selector) .Union(data)

Example 1: Find all owners of cars manufactured after 2015

import . "github.com/ahmetb/go-linq/v3"

type Car struct {
    year int
    owner, model string
}

...


var owners []string

From(cars).Where(func(c interface{}) bool {
	return c.(Car).year >= 2015
}).Select(func(c interface{}) interface{} {
	return c.(Car).owner
}).ToSlice(&owners)

Or, you can use generic functions, like WhereT and SelectT to simplify your code (at a performance penalty):

var owners []string

From(cars).WhereT(func(c Car) bool {
	return c.year >= 2015
}).SelectT(func(c Car) string {
	return c.owner
}).ToSlice(&owners)

Example 2: Find the author who has written the most books

import . "github.com/ahmetb/go-linq/v3"

type Book struct {
	id      int
	title   string
	authors []string
}

author := From(books).SelectMany( // make a flat array of authors
	func(book interface{}) Query {
		return From(book.(Book).authors)
	}).GroupBy( // group by author
	func(author interface{}) interface{} {
		return author // author as key
	}, func(author interface{}) interface{} {
		return author // author as value
	}).OrderByDescending( // sort groups by its length
	func(group interface{}) interface{} {
		return len(group.(Group).Group)
	}).Select( // get authors out of groups
	func(group interface{}) interface{} {
		return group.(Group).Key
	}).First() // take the first author

Example 3: Implement a custom method that leaves only values greater than the specified threshold

type MyQuery Query

func (q MyQuery) GreaterThan(threshold int) Query {
	return Query{
		Iterate: func() Iterator {
			next := q.Iterate()

			return func() (item interface{}, ok bool) {
				for item, ok = next(); ok; item, ok = next() {
					if item.(int) > threshold {
						return
					}
				}

				return
			}
		},
	}
}

result := MyQuery(Range(1,10)).GreaterThan(5).Results()

Generic Functions

Although Go doesn't implement generics, with some reflection tricks, you can use go-linq without typing interface{}s and type assertions. This will introduce a performance penalty (5x-10x slower) but will yield in a cleaner and more readable code.

Methods with T suffix (such as WhereT) accept functions with generic types. So instead of

.Select(func(v interface{}) interface{} {...})

you can type:

.SelectT(func(v YourType) YourOtherType {...})

This will make your code free of interface{} and type assertions.

Example 4: "MapReduce" in a slice of string sentences to list the top 5 most used words using generic functions

var results []string

From(sentences).
	// split sentences to words
	SelectManyT(func(sentence string) Query {
		return From(strings.Split(sentence, " "))
	}).
	// group the words
	GroupByT(
		func(word string) string { return word },
		func(word string) string { return word },
	).
	// order by count
	OrderByDescendingT(func(wordGroup Group) int {
		return len(wordGroup.Group)
	}).
	// order by the word
	ThenByT(func(wordGroup Group) string {
		return wordGroup.Key.(string)
	}).
	Take(5).  // take the top 5
	// project the words using the index as rank
	SelectIndexedT(func(index int, wordGroup Group) string {
		return fmt.Sprintf("Rank: #%d, Word: %s, Counts: %d", index+1, wordGroup.Key, len(wordGroup.Group))
	}).
	ToSlice(&results)

More examples can be found in the documentation.

Release Notes

v3.2.0 (2020-12-29)
* Added FromChannelT().
* Added DefaultIfEmpty().

v3.1.0 (2019-07-09)
* Support for Go modules
* Added IndexOf()/IndexOfT().

v3.0.0 (2017-01-10)
* Breaking change: ToSlice() now overwrites existing slice starting
  from index 0 and grows/reslices it as needed.
* Generic methods support (thanks @cleitonmarx!)
  - Accepting parametrized functions was originally proposed in #26
  - You can now avoid type assertions and interface{}s
  - Functions with generic methods are named as "MethodNameT" and
    signature for the existing LINQ methods are unchanged.
* Added ForEach(), ForEachIndexed() and AggregateWithSeedBy().

v2.0.0 (2016-09-02)
* IMPORTANT: This release is a BREAKING CHANGE. The old version
  is archived at the 'archive/0.9' branch or the 0.9 tags.
* A COMPLETE REWRITE of go-linq with better performance and memory
  efficiency. (thanks @kalaninja!)
* API has significantly changed. Most notably:
  - linq.T removed in favor of interface{}
  - library methods no longer return errors
  - PLINQ removed for now (see channels support)
  - support for channels, custom collections and comparables

v0.9-rc4
* GroupBy()

v0.9-rc3.2
* bugfix: All() iterating over values instead of indices

v0.9-rc3.1
* bugfix: modifying result slice affects subsequent query methods

v0.9-rc3
* removed FirstOrNil, LastOrNil, ElementAtOrNil methods

v0.9-rc2.5
* slice-accepting methods accept slices of any type with reflections

v0.9-rc2
* parallel linq (plinq) implemented
* Queryable separated into Query & ParallelQuery
* fixed early termination for All

v0.9-rc1
* many linq methods are implemented
* methods have error handling support
* type assertion limitations are unresolved
* travis-ci.org build integrated
* open sourced on github, master & dev branches

go-linq's People

Contributors

ahmetb avatar cleitonmarx avatar dericofilho avatar elimisteve avatar elliotcourant avatar golint-fixer avatar kalaninja avatar merty avatar mkitawaki avatar schigh avatar se77en avatar yoppi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-linq's Issues

Thank you.

This is an amazing library and thanks to you for this.

update website

@cleitonmarx what do you think about updating the site. You can add some info/examples of the new -T methods api and add some info about yourself.

Production use?

Really a huge fan of LINQ. I use it all the time in the front-end (map, reduce are basically the same ideas). Would love to use this package but the one question I have is---"Is this used in production by anyone?"

Add support for Go Modules

Since 1.11 Go Modules is probably the preferred way to handle versioning.
We should add support for it!

Error returned in Where method

I have seen there are lot of methods (ex: Where. Select etc ) that return error type alongside bool type. In all your examples, you are returning nil error. So when to send error other than nil and what happens if there is an error other than nil ? Thanks

using semantic versioning

Can we use a semver instead of current vx.y versioning, for better third party packaging usage?

Now I have a project using glide to manage third party deps. And glide will recognize semver if a repo have tags like v2.0.0 like this, and I can keep using a specified major version of package per build, and it wouldn't break my codes.

I think it's much cooler if go-linq use semver 😎

OrderByDescending.ThenByDescending.ThenByDescending not working correct

package xxx

import (
	"reflect"
	"testing"
	"strings"
	"fmt"
	linq "github.com/ahmetb/go-linq"
)

type Row map[string]interface{}

func maxMatricData(data []Row, groupKeys []string, metricKeys []string) []Row {
	if len(metricKeys) == 0 {
		return data
	}

	var maxData []Row
	q := linq.
		From(data).
		GroupBy(
			func(d interface{}) interface{} {
				r := d.(Row)
				var vals []string
				for _, k := range groupKeys {
					vals = append(vals, fmt.Sprintf("%v", r[k]))
				}
				return strings.Join(vals, ",")
			},
			func(d interface{}) interface{} { return d },
		).
		Select(func(g interface{}) interface{} {
			query := linq.From(g.(linq.Group).Group).
				OrderByDescending(func(r interface{}) interface{} { return r.(Row)[metricKeys[0]] })
			if len(metricKeys) > 1 {
				for _, k := range metricKeys[1:] {
					query = query.ThenByDescending(func(r interface{}) interface{} { return r.(Row)[k] })
				}
			}
			return query.First()
		}).
		OrderByDescending(func(r interface{}) interface{} {
			return r.(Row)[groupKeys[0]]
		})

       // FIXME: bug for more than 2rd order by Descending
	for _, k := range groupKeys[1:] {
		q = q.ThenByDescending(func(r interface{}) interface{} {
			return r.(Row)[k]
		})
	}
	q.ToSlice(&maxData)

	return maxData
}

func Test_maxMatricData(t *testing.T) {
	type args struct {
		data       []Row
		groupKeys  []string
		metricKeys []string
	}
	tests := []struct {
		name string
		args args
		want []Row
	}{
		{
			"default",
			args{
				[]Row{
					Row{"a": "a1", "b": "b3", "c": "1", "v1": 17, "v2": 21, "v3": 31},
					Row{"a": "a1", "b": "b1", "c": "1", "v1": 11, "v2": 21, "v3": 31},
					Row{"a": "a1", "b": "b2", "c": "1", "v1": 15, "v2": 21, "v3": 31},
					Row{"a": "a1", "b": "b1", "c": "1", "v1": 13, "v2": 21, "v3": 31},
					Row{"a": "a1", "b": "b2", "c": "1", "v1": 14, "v2": 21, "v3": 31},
					Row{"a": "a1", "b": "b1", "c": "1", "v1": 11, "v2": 22, "v3": 31},
					Row{"a": "a1", "b": "b2", "c": "1", "v1": 15, "v2": 21, "v3": 32},
				},
				[]string{"a", "b", "c"}, // passed when: []string{"a", "b"}
				[]string{"v1"},
			},
			[]Row{
				Row{"a": "a1", "b": "b3", "c": "1", "v1": 17, "v2": 21, "v3": 31},
				Row{"a": "a1", "b": "b2", "c": "1", "v1": 15, "v2": 21, "v3": 31},
				Row{"a": "a1", "b": "b1", "c": "1", "v1": 13, "v2": 21, "v3": 31},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := maxMatricData(tt.args.data, tt.args.groupKeys, tt.args.metricKeys); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("maxMatricData() = %v, want %v", got, tt.want)
			}
		})
	}
}

testing output:

--- FAIL: Test_maxMatricData (0.00s)
    --- FAIL: Test_maxMatricData/default (0.00s)
        e:\Apps\goApps\git.code.oa.com\WeishiQA\QualityHttpServer\queries\druid\handler_test.go:44: maxMatricData() = [map[a:a1 b:b3 c:1 v1:17 v2:21 v3:31] map[a:a1 b:b1 c:1 v1:13 v2:21 v3:31] map[a:a1 b:b2 c:1 v1:15 v2:21 v3:31]], want [map[a:a1 b:b3 c:1 v1:17 v2:21 v3:31]  map[a:a1 b:b2 c:1 v1:15 v2:21 v3:31]  map[a:a1 b:b1 c:1 v1:13 v2:21 v3:31]]
FAIL
FAIL	WeishiQA/QualityHttpServer/queries/druid	0.277s
Error: Tests failed.

ToSlice dose not re-empty the dist slice

Codes:

func main() {
	l := []string{"foo", "bar", "baz"}
	linq.From(l).ToSlice(&l)
	fmt.Println(l)
}

Result:

[foo bar baz foo bar baz]

go-linq version:

- name: github.com/ahmetalpbalkan/go-linq
  version: 8985ec99e11a8bff7eb19dd0a0b2187770dab23a

I don't know whether this is a bug or a feature, but if this is a feature, I think it's better to have this behavior documented on ToSlice's API doc.

question: usage with KV store.

this sounds like a good match with boltdb, in terms of doing queries in memory.

i currently use boltdb and also riak. i kind of hate riak but am stuck with it still.
i was wondering if you think that linq would help me for writing many queries i need to do on top of boltdb ?

v3: benchmark_test.go

@cleitonmarx are we actually using this benchmark_test.go file in v3-dev branch?

It looks like our travis-CI tests are not executing it. I just got this output:

$ go test -bench . .
BenchmarkSelectWhereFirst-4            	 5000000	       323 ns/op
BenchmarkSelectWhereFirst_generics-4   	 1000000	      1959 ns/op
BenchmarkSum-4                         	      30	  46626334 ns/op
BenchmarkSum_generics-4                	       3	 468433125 ns/op
BenchmarkZipSkipTake-4                 	 5000000	       301 ns/op
BenchmarkZipSkipTake_generics-4        	 1000000	      1557 ns/op
PASS
ok  	github.com/ahmetalpbalkan/go-linq	12.279s

Is there a reason for this to stay in the repo? We can perhaps make it a bit more detailed (such as specify input sizes) and still keep it in the package?

GroupBy for multiple columns

Hi,

This lib is awesome, but I didn't find any example for GroupBy for multiple columns, is it possible and supported?

thanks

the example of 'DistinctBy' is error

distinctFirstNames, err := From(people).DistinctBy(func (p T) (bool, error){
    return p.(*Person).FirstName
}).Results()

maybe:

distinctFirstNames, err := From(people).DistinctBy(func (p T,p2 T) (bool, error){
    return p.(*Person).FirstName==p2.(*Person).FirstName,nil
}).Results()

How to aggregate with group?

I would like to group by the error message and get the count of it. How can I do it using linq??

example : Slice has 100 error message, actually they are repetitive.. so I was able to group them using linq and it got reduced the group of 11 type. but I want to know the count of each group. line error 1 repeated 20 times out of 100.

ToChannelT release?

I'm having an issue getting a release with ToChannelT in it following the install directions for this package. Is there a planned release coming up with that or is there an alternative way to get get the package such that I get the version with that method? go get doesn't seem to be able to get by tag or at least it is not working for me.

Readme nitpick

In the readme.md, it says

To find names of first 5 students over 18:

But the code doesn't seem to do any ordering, so it doesn't find the "first" 5 students, just any 5 students over 18.

Append方法优化

concat.go中的Append方法,第12行i, ok := next()前面可判断一下appended是true则直接返回

Have Results() return a slice of the original type.

Currently Results() returns a slice of []T where perhaps a way to get the "original" type of the elements would be more convenient. I constantly find myself having to iterate over the []T to copy all elements to a new slice.

x, err := linq.From(f.Films).Where(func(x linq.T) (bool, error) { return true, nil }).Results()
if err != nil {
 fmt.Println(err)
}

Here x is of type []T and so I cannot reassign it to f.Films. I need to do the following:

f.Films = make([]Film, len(x))
for i, b := range x {
 f.Films[i] = b.(Film)
}

I find myself doing this kind of thing very often when using your package. Perhaps there should be a way to do this included in the package itself?

Parallel ForEach Proposal

@ahmetalpbalkan, I think the ForEach function can be an awesome feature for the library. I personally have some interesting use cases in my work that can be better expressed using the ForEach approach.

This code is another try to implement the @kalaninja idea:

func (q Query) ForEach(c chan interface{}, action func(interface{})) {
	next := q.Iterate()
	if c == nil {
		for item, ok := next(); ok; item, ok = next() {
			action(item)
		}
	} else {
		var wg sync.WaitGroup
		for item, ok := next(); ok; item, ok = next() {
			wg.Add(1)
			go func(wg *sync.WaitGroup, item interface{}) {
				defer wg.Done()
				action(item)
			}(&wg, item)
		}

		go func() {
			wg.Wait()
			close(c)
		}()
	}
}

This provides an elegant way to solve the concurrent example problem:

results := make(chan interface{})
domains := []string{"www.google.com", "www.github.com", "www.facebook.com"}

From(domains).
    Select(func(d interface{}) interface{} {
        return fmt.Sprintf("http://%s/favicon.ico", d)
    }).
    ForEach(results, func(url interface{}) {
	  resp, _ := http.Get(url.(string))
	  results <- resp.StatusCode
    })

count := FromChannel(results).CountWith(func(r interface{}) bool {
    return r.(int) == 200
})

fmt.Println("Count:", count)

Or just for run simple tasks in parallel:

From(domains).
    Select(func(d interface{}) interface{} {
	return fmt.Sprintf("http://%s/favicon.ico", d)
    }).
    ForEach(results, func(url interface{}) {
	resp, _ := http.Get(url.(string))
	fmt.Println(url.(string), "->", resp.StatusCode)
    })

<-results

fmt.Println("Finished all tasks")

If no channel was provided, ForEach will iterate sequentially as proposed by @kalaninja.

question: clipperhouse & gen

Hello. I stil getting into go and learning. I used to do OOP languages, so excuse the newbie questions.
This is really nice to see in Golang.

Does this generate at design time ?

Have you thought about design time using clipperhouse gen ?

Have you thought about an JSON like definition of the data types, and gen the types and then gen the query layer ?

custom query functions - mean, median

First of all, thanks for simple and super useful library!!

Only thing I would like to see added is a way to add custom functions like Average. I know there are multiple functions readily available, but what if I want to do Mean, Median or some kind of custom processing on values. It doesn't expose values to outside world as well. So kind of feels restricted.

If you have any thoughts on this, please share, I can try implementing it.

Passing in Array of fields for SortByT

When looking at a language such as Ruby, one can pass in an array of fields to do multi-level sorting ( i.e. "sort by last name, first name" ).

Currently it does not seem possible to do this in go-linq

go-linq to c linq

I know this may not related to you go-linq code.

I want to write some linq library using c, and reference your go-linq code, but it just core dumps.

Below is the c code:

#include <stdio.h>
#include <stddef.h>
#include "vec.h"

#define bool int
#define true 1
#define false 0

#define lambda(ret, body) ({ ret __fn__ body __fn__; })

typedef bool (*Iterator)(void*);
typedef Iterator (*Iterate)(void);

typedef bool (*Predicate)(void *);

typedef struct Query {
    Iterate iterate;
}Query;


Query From(void *source) {
    vec_void_t *v = (vec_void_t *)source;
    int len = v->length;

    Iterator iter() {
        int index = 0;

        bool iterator(void *item) {
            item = NULL;
            bool ok = index < len;
            if (ok) {
                item = v->data[index];
                index++;
            }
            return ok;
        }

        return iterator;
    }

    Query result;
    result.iterate = iter;
    return result;
}

Query Where(Query *q, Predicate predicateFn) {
    Iterator iter() {
        Iterator next = q->iterate();
        bool iterator(void *item) {
            bool ok = false;
            for (ok = next(item); ok; ok = next(item)) {
                if (predicateFn(item)) {
                    return ok;
                }
            }
            return ok;
        }

        return iterator;
    }

    Query result;
    result.iterate = iter;
    return result;
}

vec_void_t Results(Query *q) {
    vec_void_t v;
    vec_init(&v);
    Iterator next = q->iterate();
    bool ok = false;
    void *item = NULL;
    for (ok = next(item); ok; ok = next(item)) {
        vec_push(&v, item);
    }

    return v;
}

int main() {
    vec_void_t v;
    vec_init(&v);

    int i, j, m, n;

    i = 1;
    vec_push(&v, &i);

    j = 2;
    vec_push(&v, &j);

    m = 3;
    vec_push(&v, &m);

    n = 4;
    vec_push(&v, &n);

    int w = 0;
    for (w = 0; w < 4; w++) {
        printf("v[%d] = %d\n", w, *((int *)v.data[w]));
    }

    Query qFrom = From(&v);
    Query qWhere = Where(&qFrom, lambda(bool,  (void *v) {
                      int i = *(int *)v;
                      return i / 2 == 0;
                }));

    vec_void_t vResults = Results(&qWhere);

    for (w = 0; w < 4; w++) {
        printf("vResults[%d] = %d\n", w, *((int *)vResults.data[w]));
    }

    vec_deinit(&v);
    return 0;
}

The above c code core dump at Iterator next = q->iterate(); line of function Results.

Could you kindly tell me why the c code doesn't work? and how to fix that?

Thanks in advance.

From() should also take channel as input

Instead of taking an array / a slice as input, From() should also take a channel as input. It would provide far more flexibility.

For example,

import . "github.com/ahmetalpbalkan/go-linq"

type Student struct {
    id, age int
    name string
}

func example_usage() {
    ch := make(<-chan Student)
    DBStudentToChan(ch) // some function that outputs to the channel

    over18Names, err := From(ch)
        .Where(func (s T) (bool,error){
            return s.(*Student).age >= 18, nil
        })
        .Select(func (s T) (T,error){
            return s.(*Student).name, nil
        }).Results()
}

PLINQ support

PLINQ removed for now (see channels support)
Where can I see channels support? Is there any example about this?
Thanks

FAQ addition:

could a question and (hopefully an answer) be added to the FAQ along the lines of: "Are linq result slices guaranteed to be assigned new underlying arrays to avoid any memory management issues?"

Try out the new Go generics proposal with go-linq

Go now has a prototype of generics implementation. Here are some resources:

This potentially could give a severe performance boost to go-linq, as well as actually make this library useful.

I haven't taken a closer look at how we would do this yet. For example, we might still end up having to do some type assertions. However, it might help us redesign the package and release a v4 if the generics proposal is adopted.

Does first return a copy?

Hi guys,

I'm trying to use the package and either I don't understand something or First returns a copy of the element. Here is a simple example:

collection := Items{
	Item{
		ID:    1,
		Title: "title 1",
	},
	Item{
		ID:    2,
		Title: "title 2",
	},
}

item1 := From(collection).FirstWith(func(m interface{}) bool {
	return m.(Item).ID == 2
})
fmt.Printf("%p \n", &item1)
item2 := From(collection).FirstWith(func(m interface{}) bool {
	return m.(Item).ID == 2
})
fmt.Printf("%p \n", &item2)

Output:

0xc4204445d0 0xc4204445e0

As you can see the same element gets two different address allocation.
How can I get a pointer to my initial element?

panic while `OrderBy` on an empty slice

Codes:

func main() {
	linq.From([]string{}).OrderBy(func(in interface{}) interface{} {
		return 0
	}).Results()
}

OrderBy on a non-empty slice which have a Where filter, and the filter will filter all the elements, will cause the bug too.

Stack trace:

panic: runtime error: index out of range

goroutine 1 [running]:
panic(0x437ce0, 0xc42000c0f0)
	/usr/local/Cellar/go/1.7.3/libexec/src/runtime/panic.go:500 +0x1a1
github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq.Query.sort(0xc420385170, 0xc42038ede0, 0x1, 0x1, 0xc42038edc0, 0x0, 0x743200)
	/Users/asaka/Codes/go/src/github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq/orderby.go:177 +0x235
github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq.Query.OrderBy.func1(0x45e5c0)
	/Users/asaka/Codes/go/src/github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq/orderby.go:28 +0x8d
github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq.Query.Results(0xc42038edc0, 0x546ec0, 0xc42038edc0, 0xc420385170)
	/Users/asaka/Codes/go/src/github.com/leancloud/lean-cli/lean/vendor/github.com/ahmetalpbalkan/go-linq/result.go:208 +0x2e
main.main()
	/Users/asaka/Codes/go/src/github.com/leancloud/lean-cli/lean/main.go:299 +0xf0

go-linq version:

- name: github.com/ahmetalpbalkan/go-linq
  version: 8985ec99e11a8bff7eb19dd0a0b2187770dab23a

(current master branch codes).

Linq to SQL

Hi there,

first of all thanks for this cool library.
I'm wondering whether there are any plans to extend the lib in order to be able to build Expression Tree and use it for doing DB queries. Not sure, it's possible with Go's capabilities, though.

Query.Difference

Hi there,

First of all thanks this cool library.

I'm thinking about there is any plans to extend this lib with func Query.Difference besides Query.Intersect and Query.Union.

[announcement] Changing username for the repo

I am planning to change my GitHub username to ahmetb soon. If you already vendored this repo (which you should) this change is not going to break your builds, it may cause issues when you try to update the vendored package.

Leaving this issue open for a while to discuss issues that come up because of the change.

How can I extract same element from a slice then append into a map

I have a slice like this following:

type Post struct {
  title          string
  category  string
}

post1 := Post{"a1", "hello"}
post2 := Post{"a2", "hello"}
post3 := Post{"a3", "world"}

posts := []*Post{&post1, &post2, &post3}

I wanna extract this posts slice to a map like this:

postMap := make(map[string][]string)

So the category is string key and title is a slice value, when I call postMap["hello"] it return a slice include post1 and post2 and when I call postMap["world"] it will return post3.

How can I get this use go-linq? please help

How to implement complex SQL functions

How to implement complex SQL functions similar to the following

type TransactionRecord struct {
	ID        uint64
	AccountID string
	TCode     string
	TDate     string
	TType     uint8
	Amount    float64
}

var tds []TransactionRecord
t1 := TransactionRecord{ID: 1, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 17, Amount: 23.0}
t2 := TransactionRecord{ID: 2, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 17, Amount: 99.0}
t3 := TransactionRecord{ID: 3, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 17, Amount: 25.0}

t4 := TransactionRecord{ID: 1, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 24, Amount: 13.0}
t5 := TransactionRecord{ID: 2, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 24, Amount: 69.0}
t6 := TransactionRecord{ID: 3, AccountID: "A001", TCode: "161700", TDate: "2020-08-01", TType: 24, Amount: 85.0}
		
t7 := TransactionRecord{ID: 4, AccountID: "A001", TCode: "161700", TDate: "2020-08-02", TType: 17, Amount: 11.0}
t8 := TransactionRecord{ID: 5, AccountID: "A001", TCode: "161700", TDate: "2020-08-02", TType: 17, Amount: 33.0}
t9 := TransactionRecord{ID: 6, AccountID: "A001", TCode: "161700", TDate: "2020-08-02", TType: 17, Amount: 57.0}
		
tds = append(tds, t1)
tds = append(tds, t2)
tds = append(tds, t3)
tds = append(tds, t4)
tds = append(tds, t5)
tds = append(tds, t6)
tds = append(tds, t7)
tds = append(tds, t8)
tds = append(tds, t9)

I want to implement the following SQL functions, how to write code with go-linq package

select AccountID,TCode, TDate,TType, sum(Amount)  as am from TransactionDetails where TType = 17 or TType = 24 GROUP BY AccountID, TCode,TDate, TType ORDER BY AccountID, TCode,TDate, TType;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.