Git Product home page Git Product logo

linq.lua's Introduction

LINQ for Lua

This project is an implementation of the LINQ system in Lua.

LINQ (Language-Integrated Query) is a library originally in the .NET framework that adds some consitent and powerful query features on enumerable types.

The aim of this project is to keep an API that is close to the original and to use the same deferred execution methods with CPU and memory usage efficiency in mind.

Usage

Basic usage

Here is a simple example on how to import and use the library into a project:

-- Import the "Linq" namespace
local Linq = require "linq";

-- Add the "List" class into the "Linq" namespace
require "list";

-- Creates a new instance of the "List" class that is initialized with the given array
local scores = Linq.List.New({
    {Name = "Alice", Score = 84},
    {Name = "Bob", Score = 92},
    {Name = "Cathy", Score = 88}
});

-- Execute a query
local admitted = scores
    :Where(function(s) return s.Score >= 85; end)
    :Select(function(s) return s.Name; end)
    :ToArray();

-- admitted: {"Bob", "Cathy"}

You can also use LibStub to use this library in an addon for the game World of Warcraft:

# MyAddon.toc

## Interface: 80300
## Title: MyAddon
## Author: Draghos
## Version: 0.0.1

# You need LibStub first
Libs/LibStub/LibStub.lua

# Import linq.lua
Libs/Linq/linq.lua

# Then import optional collections
Libs/Linq/list.lua
Libs/Linq/hashSet.lua

# Lastly import the files in which you want to use Linq
MyAddon.lua
-- MyAddon.lua

-- Import Linq using LibStub
local Linq = LibStub("Linq");

-- You can now use the collections you have imported and Enumerable operations
local list = Linq.List.New(Linq.Enumerable.Range(1, 5));

Type inference

To get type inference, you need to install EmmyLua (available on IntelliJ and VSCode) and use the following line just after the require statements:

local Linq = require "linq";
require "hashSet";

--- @type HashSet
local HashSet = Linq.HashSet;

-- ... use HashSet instead of Linq.HashSet

Sometimes EmmyLua doesn't detect inheritance, in which case you need to declare it yourself:

--- @type List|ReadOnlyCollection|Enumerable
local List = Linq.List;

Defining and executing a query

The execution of queries is deferred until an operation that actually returns a result is called, and only the elements that are needed in the final result are processed.

For instance, in the following example the first Select is called six times (from index 1 until the end of the iteration at index 6), even though the source array has ten items, and the second Select is called only three times, because it is executed after the Skip and Take operations:

local initialEnumeration = 0;
local finalEnumeration = 0;

local query = Enumerable.Range(1, 10)
    :Select(function(n) initialEnumeration = initialEnumeration + 1; return n; end)
    :Skip(3)
    :Take(3)
    :Select(function(n) finalEnumeration = finalEnumeration + 1; return n; end);

-- initialEnumeration: 0
-- finalEnumeration: 0

local results = query:ToArray();

-- initialEnumeration: 6
-- finalEnumeration: 3
-- results: {4, 5, 6}

You can also extend and execute a query multiple times after declaring it:

local query = List.New({1, 2, 3, 4, 5})
    :Where(function(i) return i >= 2; end)
    :Skip(1);

local result;

result = query:ToArray();
-- result: {3, 4, 5}

result = query:Reverse():ToArray();
-- result: {5, 4, 3}

result = query:Skip(1):Take(1):ToArray();
-- result: {4}

result = query:Sum();
-- result: 12

It is possible to use another enumerable as an argument for an operation:

local first = List.New({1, 2, 3, 4, 5});
local second = List.New({6, 7, 8});

local query = Enumerable.From(first):Concat(second);

local result;

result = query:ToArray();
-- result: {1, 2, 3, 4, 5, 6, 7, 8}

second:Add(9);
result = query:ToArray();
-- result: {1, 2, 3, 4, 5, 6, 7, 8, 9}

Using collections

Several collections implementing the Linq operations are provided. Each type of collection has its pros and cons but all of them can be used as enumerables.

ReadOnlyCollection

This is the base collection that is used when calling a method like Linq.Enumerable.From.

This ReadOnlyCollection takes a table as source and use it to perform operations but it is not possible to add, remove or modify items on it.

List

The List inherits from ReadOnlyCollection except that it uses a shallow copy of the source sequence and it contains some operations that allow to modify it. The source sequence is not modified by the actions performed on the list (for instance, when calling list:Add(item) it will add the item on the list instance but not on the table that was used to create the list).

HashSet

A HashSet is a collection that contains no duplicate items. The duplicate items are determined by using the equality operator (==) or by using a given function used as a comparator (but in this case it will be slower). The items in the set are in no particular order.

This type provides some interesting mathematical methods to add or remove items such as set additions (unions) or substractions (excepts).

Dictionary

The Dictionary is a collection of key/value pairs in which the order of elements is respected as they are added into the collection. Each key must be unique according to the default equality operator (==) or a comparison function.

Note: You need to import List in order to use the Dictionary.

Limitations

It is not possible to call Linq methods directly on a table object, so this will throw an error:

local t = {1, 2, 3};
t:Sum(); -- Error
Enumerable.From(t):Sum(); -- Use this instead

API

Enumerable

Name Immediate Deferred Type
Aggregate X
All X
Any X
AsEnumerable
Average X
Concat X
Contains X
Count X
DefaultIfEmpty X
Distinct X
ElementAt X
ElementAtOrDefault X
Empty Static
Except X
First X
FirstOrDefault X
From Static
GroupBy X
GroupJoin X
Intersect X
Join X
Last X
LastOrDefault X
Max X
Min X
OrderBy X
OrderByDescending X
Range Static
Repeat Static
Reverse X
Select X
SelectMany X
Single X
SingleOrDefault X
Skip X
SkipWhile X
Sum X
Take X
TakeWhile X
ToArray X
ToDictionary X
ToHashSet X
ToList X
ToLookup
Union X
Where X
Zip X

OrderedEnumerable

Name Immediate Deferred Type
ThenBy X
ThenByDescending X

List

Name Side-effect Type
Add Yes
AddRange Yes
Clear Yes
Contains
CopyTo
Exists
Find
FindAll
FindIndex
FindLast
FindLastIndex
ForEach
GetRange
IndexOf
Insert
InsertRange
LastIndexOf
Length Property
New Static
Remove
RemoveAll
RemoveAt Yes
RemoveRange
Reverse
Sort
ToArray
TrueForAll

HashSet

Name Side-effect Type
Add Yes
Clear Yes
Contains
Comparer Property
CopyTo
Length Property
New Static
Remove Yes
RemoveWhere
IsProperSubsetOf
IsProperSupersetOf
IsSubsetOf
IsSupersetOf
Overlaps
SymmetricExceptWith Yes
TryGetValue
UnionWith Yes

Dictionary

Name Side-effect Type
Add Yes
Clear Yes
ContainsKey
ContainsValue
Comparer Property
Length Property
New Static
Keys Property
Remove Yes
TryAdd Yes
TryGetValue
Values Property

linq.lua's People

Contributors

vadri avatar

Stargazers

li5414 avatar

Watchers

 avatar

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.