🗐 QuickList - Making Lua tables better

Quicklist_logo
GitHub | Library | Wally

What is it :question:

Quicklist is a custom class made for tables, which adds a simple way of creating custom tables and adds more features to them. Any table you create has functions that can be called on the table itself, rather than using a library such table.insert() is now myTable.insert(). Most of the new features were taken from either python, js, or something else.

  • Here’s the github from where you can get the QuickList.lua “latest” module. And some documentation examples are given here.
  • Here’s the ModuleScript from the asset library.

Documentation :spiral_notepad:

Majority of the documentation is in the README.md in the github, I’ll just post some of the features and getting started things, you should use the github for latest things.


Getting Started :white_check_mark:

Go to the github source code or releases and get QuickList.lua. Copy paste this code into a ModuleScript and put it in ReplicatedStorage. (or use it directly in a .lua file.)


Once the module is created use require(pathToModule). The function returned is the new function by default. Just name the variable something short and put it at the start when making a table. Such that {} turns to _{}. (I named the variable underscore but you can name it anything you want.)

local _ = require(game:GetService("ReplicatedStorage").QuickList)
local myTable = _{'hello', 'world'} -- Use underscore before making the table
print(myTable)

Output:

> {hello, world}

It also has a built-in __tostring() function for whenever it’s printed.


Table → QuickList / Quicklist → Table :cancer:

You can either use ql{'hi'} or use ql(table) as a function.
Use ql.get_table() to get a normal table (without any metatable or quicklist stuff).


Indexing the table :dart:

Single index

The same as a normal table, indexes start at 1 and you can use square brackets [] to get the index.

local myTable = _{'hello', 'world'}
print(myTable[2]) -- prints 'world'

Ranged index (Slicing)

This returns a new copy of the table from the range specified. Use curly brackets {} and inside use this format {_start, _end, _skip}.

  • _start: Starting index.
  • _end: Ending index. (Defaults to the end of the script)
  • _skip: Skip between values. Default is 1, changing it to 2 will give you every second value.
local myTable = _{'hello','world','foo','bar',100, nil}
local Range = myTable{2,4}
print(Range) -- prints {'world', 'foo', 'bar', 100}

Negative indexing

QuickList supports negative indexing, such that myTable[0] will be the last value and myTable[-1] will be second last, and so on.
This also works the same with range indexing so you can do

local myTable = _{}.string('a b c d e f g h j k l') -- Split string by space.
print(myTable[0]) -- prints 'l'
print(myTable[-1]) -- prints 'k'
print(myTable{1, -3}) -- prints {a,b,c,d,e,f,g,h}

Methods :calling:

Methods

Quicklist has a lot of methods, but you’ll find some of them listed here:

self.copy()

Creates a shallow copy of the Quicklist (not linked to any other).

self.insert(pos,value)

Insert a value at specific position pos. Pushes everything forward.

self.append(value)

Add a value to the end of the table.

self.join(sep)

Join the table into a string. (separated by sep)

self.split(index)

Split the table into a Quicklist with 2 Quicklists. {{}, {}}

self.sort(comp)

Sort the table. Default ascending. Pass in comp as “descending” or a function(a,b).

self.forEach(func)

Loop through the value, calling func(value) at each interval.

self.enumerate(func)

Loop through the value, calling func(index, value) at each interval.

self.merge(tab)

Merge this list with another one.

self.rep(value, times)

Add same value multiple times to the end.

self.remove(pos)

Remove a value at position.

self.pop()

Remove a value AND get the removed value returned back.

self.move(pos1, pos2)

Move a value from one position to another.

self.reverse()

Get a reversed copy of the table.

self.string(str, sep)

Split a string into a QuickList and separate using the sep.

self.find(value)

Returns the first index of the value if it exists, and nil if it doesn’t.

self.occurrences(value)

Get how many times a value is in the list.

self.unique()

Get a unique copy of the table where no value is repeated.

self.get_dictionary()

Get a dictionary formatted {[1] = 'hello', [2] = 'world'}

self.shuffle()

Returns a shuffled copy of the table.

self.random()

Get a pseudo-radom value from the table.

self.flatten()

Flatten the table, recursively looping and flattening every table inside.

self.average()

Get an average of every number in the table.

self.startsWith(tab)

Check if the table starts with a sequence tab.

self.endsWith()

Check if the table ends with a sequence tab.

self.checkql()

Check if the table is a QuickList.

self.sum()

Returns the sum (number) of all the number values (and number strings) in the table.


The QuickList follows OOP and currently doesn’t support library functions.
Most metamethods of the table are handled automatically.
If you want to use it in an existing project just prefix your list creation with the returned value from the require().

Have fun using it :sunglasses:

27 Likes

v1.0.1

  • Added negative indexing.
  • Fixed flatten()
4 Likes

I see this have a lot of potential, it’s quick and easy to use.

3 Likes

v1.0.2

  • Fixed a lot of stuff
  • added __eq metamethod
  • added __add metamethod
  • added __lt and __le metamethods
  • added __concat metamethod
  • fixed copy()
  • average() now only divides with how many numbers are in the list (before it did the length of the entire list)
  • added sum() function which adds all number values and returns the output

I think that’s all.

Uploaded the QuickList module to Roblox.
:+1:

Mayhaps, I will use this.

Also this 30 limit sucks

2 Likes

Very cool, i’ve always hated roblox’s table system
I’ll try this out later!

1 Like

v1.0.2.1

This is a sub-fix and not a full release but I have updated the source on github and the ModuleScript. (Not the github releases)

  • Added the ability to remove things in the table using the object/string itself.
  • added self.setEach(func) which takes in a function call back and calls func(i,v) and the returned value each iteration is set to the current value. (I didn’t add this in the module yet)
local myTable = _{'hi', 'bye'}
myTable.setEach(function(i, v)
    if v == 'hi' then
        return 'good'
    end
    return v
end)
print(myTable) -- prints {good, bye}

Very cool and useful plugin with a lot of potential!
However you might want to consider using self[#self + 1] = value for the .append function as I heard it is faster.

Edit: Forgot to mention .insert but you should do the same thing with it

1 Like

Huh, I never thought it was faster. I’m using table.insert(pos, value) for appending and same for inserting. I don’t know how fast both are but if someone could benchmark it that would be useful. Insert just automatically pushes everything forward so I don’t really care much though.

Also it’s not a plugin lol its just a module. (joke)
Thanks :+1:

Just to clarify, this module makes lists better, not quicker? Why is it called QuickList then? It’s impossible to make lists faster than normal luau lists because you need to use them to do that.

QuickList now works with CactusBase 2

Can I use this with QuickList?

Yes, setting data is possible using my QuickList class. Unfortunately, the data returned from GetAsync() is a dictionary and you’ll have to re-convert the returned data into a quicklist. It’s as simple as doing _( data ). Also I don’t suggest using arrays as it’s cleaner using dictionaries.

Go check out CactusBase 2 as well.

2 Likes

The reason I called it QuickList was because BetterTable was already taken, and also the fact that these only work for the array side of things.
I doubt these run faster than table and table methods themselves. Probably because I’m using the table functions to work with tables. There’s no way around that in Luau and I don’t have enough freedom or knowledge to make these faster. Suggestions to make things faster and better are always appreciated.

QuickList just reduces the amount of lines needed for the same functionality and let’s you use self and table objects rather than doing table.method(table, args).

2 Likes

It’s not really faster by a lot (I used a for i = 1, 10000000 loop) , but it’s still faster. However do whatever you think looks better (code-wise) for you, since no one is going to use the methods 10,000,000 times simultaneously lol
image

2 Likes

Cool module, but if someone isnt a fan of OOP I can highly recommend Sift which adds a lot of the same functionality QL adds but using the functional paradigm

1 Like

Honestly the entire point of QuickList is that it’s based on OOP.
You could just use the normal table.method(table, args) library and work normally. But mine provides OOP and more functionality, it’s pretty much a wrapper over the normal one.

3 Likes

after testing around with it for a while i found out that string indexing isnt supported most likely due to tonumber(key) in the __index function of the metatable

Yeah so in the latest update (check github) I think I added string indexing. If not then you’ll have to wait.

v1.0.3

A lot of new changes!

  • Autocomplete now works better and you can see all the functions of the QuickList table
  • Chaining also supports autocomplete
  • Added setEach(function(i, v))
  • Module code was revamped and is slightly easier to look around.
  • Removed as many warnings as possible in the Roblox code editor.
  • .new() method assert text was changed. (“Nil, table or QuickList must be provided.”)
  • get_dictionary() was renamed to get_table()

Big change

Quicklist now has “support” for dictionaries. The only thing that works in it is

  • Creating dictionaries using
local _ = require('QuickLIst')
_{
    hello = 'world'
    test = {
        foo = 'bar'
    }
}
  • Remove a key-value pair from a dictionary. table.remove(key:string)
  • Printing/tostring dictionaries + arrays change.

Thanks @Cookibot on github for helping me with some stuff such as the autocomplete and forking the repo.

Speaking of dictionaries, I don’t know if I should keep support for them or get rid of support entirely.

Give ideas on what I could add though. remove(key_name) is the only known supported function as of now.