{"id":20552533,"url":"https://github.com/sup2point0/weighted-list","last_synced_at":"2026-02-28T02:47:03.137Z","repository":{"id":109126585,"uuid":"488723304","full_name":"Sup2point0/weighted-list","owner":"Sup2point0","description":"A list of weighted items for weighted selection and randomisation, available in both Python and C#","archived":false,"fork":false,"pushed_at":"2024-05-23T07:35:27.000Z","size":128,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-23T08:39:11.971Z","etag":null,"topics":["csharp","list","python","random","utilities","utilities-csharp","utilities-python","utility","utility-classes","weighted","weighted-random"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sup2point0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-04T19:45:15.000Z","updated_at":"2024-05-23T07:35:30.000Z","dependencies_parsed_at":"2024-04-04T11:25:29.320Z","dependency_job_id":"e68ccdc7-24e6-478d-a43c-bc5b0393a49c","html_url":"https://github.com/Sup2point0/weighted-list","commit_stats":null,"previous_names":["sup2point0/weighted-list"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sup2point0%2Fweighted-list","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sup2point0%2Fweighted-list/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sup2point0%2Fweighted-list/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sup2point0%2Fweighted-list/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sup2point0","download_url":"https://codeload.github.com/Sup2point0/weighted-list/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242157271,"owners_count":20081041,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","list","python","random","utilities","utilities-csharp","utilities-python","utility","utility-classes","weighted","weighted-random"],"created_at":"2024-11-16T02:36:32.608Z","updated_at":"2026-02-28T02:46:58.110Z","avatar_url":"https://github.com/Sup2point0.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e \u003ccode\u003e weighted-list \u003c/code\u003e \u003c/h1\u003e\r\n\r\n\u003cdiv align=\"center\"\u003e\r\n  \u003cimg src=\"https://github.com/Sup2point0/weighted-list/actions/workflows/test-py.yml/badge.svg\"\u003e\r\n  \u003cimg src=\"https://github.com/Sup2point0/weighted-list/actions/workflows/test-cs.yml/badge.svg\"\u003e\r\n\u003c/div\u003e\r\n\r\nA class representing a list of weighted items, implemented (eventually) in every language I’ve learnt.\r\n\r\n\r\n```py\r\n# Python\r\ngreetings = WeightedList(\r\n  (20, \"sup\"),\r\n  (2, \"salutations\"),\r\n)\r\n\r\nprint(greetings.select())\r\n# sup\r\n```\r\n\r\n```cs\r\n// C#\r\nWeightedList\u003cstring, int\u003e greetings = new(\r\n    (2, \"sup\"), (20, \"salutations\")\r\n);\r\n\r\nConsole.WriteLine(greetings.GetRandomValue());\r\n// salutations\r\n```\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Purposes\r\n\r\n\u003e [!TIP]\r\n\u003e For the full rationale behind this project, see [rationale](rationale.md).\r\n\r\nMainly intended for *weighted randomisation*, where each element can have a different chance of being selected (its weight).\r\n\r\nThe prime example of this is lootbox or reward systems in games, where items have different rarities.\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Features\r\n\r\n- Randomised selection with a variety constraints\r\n- Convenience methods to manipulate values and weights\r\n- Separate methods with and without side effects for flexibility\r\n- Conversions from and to a wide range of other data types\r\n\r\n### Future\r\n- Slice indexing[^slice]\r\n\r\n[^slice]: Really quite difficult with non-integer weights.\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Usage\r\n\r\nThe project is not available as a package.[^package] Instead, just download the relevant files, or copy and paste the code directly.\r\n\r\n[^package]: I don’t think it’s a large enough project to warrant an entire package, when you could just copy and paste the code directly.\r\n\r\n\u003e [!TIP]\r\n\u003e Walkthroughs and specimens for each language can be found in their respective folders.\r\n\r\n### Python\r\nAll you need is the [`weightedlist.py`](python/source/weighted_list.py) file, which contains the `WeightedList` class with all the functionality. Simply import it, and you’re ready to go!\r\n\r\n```py\r\nfrom weightedlist import WeightedList\r\n```\r\n\r\nSee [walkthrough](python/walkthrough.md) for a tutorial, or [examples](python/examples.md) for examples.\r\n\r\n\u003c!--\r\n### Implementation\r\nA `WeightedList` works just like how a `list` does, except rather than storing the values themselves, it stores `WeightedItem` objects. The value and weight of each item can be accessed through the `value` and `weight` attributes, respectively. These are passed in as pairs when instantiating the list:\r\n\r\n```py\r\nwl = WeightedList(\r\n  (2, \"sup\"),\r\n  (7, \"nova\"),\r\n  (13, \"shard\"),\r\n  ...\r\n)\r\n```\r\n\r\nThe `weight` of each item can be thought of as how many duplicates are stored (which would replicate the weighting mechanic):\r\n\r\n```py\r\n\u003e\u003e\u003e wl = WeightedList(sup = 2, nova = 7)\r\n\r\n\u003e\u003e\u003e wl[0].value\r\n'sup'\r\n\u003e\u003e\u003e wl[1].value\r\n'sup'\r\n\u003e\u003e\u003e wl[2].value\r\n'nova'\r\n\u003e\u003e\u003e wl[8].value\r\n'nova'\r\n\r\n\u003e\u003e\u003e wl.selects(7)\r\n['nova', 'sup', 'nova', 'nova', 'sup', 'nova', 'nova']\r\n# 'nova' has a higher change of being selected\r\n```\r\n--\u003e\r\n\r\n### C#\r\nAll the code is contained within the [`WeightedList.cs`](c-sharp/weighted-list/weighted-list.cs) file. You might also need the [`weighted-list.csproj`](c-sharp/weighted-list/weighted-list.csproj) file.\r\n\r\nIf you want the entire solution, you can download the repo and extract the [`c-sharp/`](c-sharp/) folder. This also contains tests to verify that everything is working.\r\n\r\nFor a tutorial, see [walkthrough](c-sharp/walkthrough.md).\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Compatibility\r\n\r\n### Python\r\n- Made in Python 3.11\r\n- All imports are from the standard library, so there are no external dependencies\r\n\r\n### C#\r\n- Made in C# 12.0\r\n- Supports LINQ querying\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Notes\r\n\r\n- Due to the nature of weighted indexing, random access has a time complexity of $O(n)$, where $n$ is the number of elements in the list.\r\n  - However, optimising this further without significant sacrifices in space complexity (which is already decently hefty) appears unviable.\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT license, so feel free to use it however you wish (although some credit would be cool!).\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Questions\r\n\r\n### Why did you create this?\r\nBack when I was picking up the ropes of Python, I was working on a project which featured randomisation, and, like any game developer, I thought it’d be cool to give each outcomes different probabilities of occurring. At first, I achieved this behaviour by duplicating items, but I quickly realised the numerous issues with this.\r\n\r\nAnd so, I set out to write my own class, which I’d never really needed to do up until that point. I thought it’d be a great exercise in learning Python – and it very much was, teaching me tons about object-oriented programming, dunder methods, generators, etc. It was also my first experience of conscientiously writing code that wasn’t exclusively for myself, which helped me understand the importance of consistency and clarity, and above all, documentation.\r\n\r\nA couple years later, I’ve come back to do the same in C#, this time also adding several features I always intended to add but never did – especially non-integer weights, which allows the class to truly embrace its usage as representing probabilities. Trying to translate Python into C# was an interesting experience,[^translate] and helped highlight some important differences between the languages that I would otherwise not have found out.\r\n\r\n[^translate]: This was not exactly the way I created the project in C#, but the Python implementation certainly laid out a general framework and was influential in some design decisions.\r\n\r\n### Is this even useful?\r\nI mean yeah, a whole several-hundred-lines class to handle one thing might be a bit overkill. But it’s far more convenient to have it all packaged this way into a single portable file that can easily be slotted into other projects. Regardless, I’ve used my own code[^surprise] in at least 2 major projects ([PENGUIN\u003csup\u003e↗\u003c/sup\u003e](https://github.com/Sup2point0/PENGUIN) and [Algorhythm\u003csup\u003e↗\u003c/sup\u003e](https://Sup2point0/Algorhythm)), so I can definitely say it’s been useful to me!\r\n\r\n[^surprise]: To my own surprise, somewhat.\r\n\r\n### Why are the source files several hundred lines long?\r\n1, documentation; 2, line breaks; 3, extra functionality. Particularly documentation. That stuff just *eats* the line count. Also, implementing something as complex as an enumerable container requires a lot of methods, operators and interfaces, both in Python and C#. And in C# you've even got overloading to account for as well.\r\n\r\n### Is the code that optimised?\r\nI have tried to ensure everything is implemented as efficiently as possible, but I cannot guarantee every single part is perfectly optimised, and I haven’t gone to the extremes of timing different approaches. Operations that may take longer than expected will likely have that mentioned in their documentation (docstrings for Python, XML comments for C#).\r\n\r\n### Why is your Python code not compliant to PEP 8?\r\nI have my own particular preferences when it comes to coding in Python, which I explain fully [here\u003csup\u003e↗\u003c/sup\u003e](https://github.com/Sup2point0/Assort/blob/origin/~dev/Python%20Syntax.md).\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n## Contribute\r\n\r\nAny feedback, suggestions or improvements are definitely welcome!\r\n\r\n\r\n\u003cbr\u003e\r\n\r\n\r\n\u003c!-- what you lookin at? --\u003e\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsup2point0%2Fweighted-list","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsup2point0%2Fweighted-list","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsup2point0%2Fweighted-list/lists"}