I am trying to arrange this multidimensional array to ascending or descending. However, I need the relation between column 1 and 2 to still be together(meaning I need the data of eg. array[0,1] and array[0,2] to be together or related in some way or another. This are my codes as of right now.
int[,] time = new int[5,2]{{0,4},{1,5},{5,10},{3,4},{0,2}};
var sorted = from x in Enumerable.Range(0, time.GetLength(0))
from y in Enumerable.Range(0, time.GetLength(1))
select new{
X = x,
Y = y,
Value = time[x,y]
}into point
orderby point.Value descending
select point;
This works but it splits all my data apart. Is there a way to sort them while keeping the relation of column 1 and 2 together?
I'm curious as to why you need a multidimensional array. It's clear you are treating your data as a single-dimensional collection of "rows," rather than a 2-dimensional collection of "cells."
Why not simply make a List(T), where T is some sort of Tuple or custom struct?
On the surface, it seems like you're trying to use a screwdriver on a nail; make sure you're picking the right tool for the job ;)
It sounds like you want to store your data in a multi-dimensional array, but keep each row in the array as a separate atomic unit. And additionally, the comparison of each "point" is by X, and then Y.
int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 5, 10 }, { 3, 4 }, { 0, 2 } };
var sorted = from x in Enumerable.Range(0, time.GetLength(0))
select new Point()
{
X = time[x,0],
Y = time[x,1]
} into point
orderby point.X ascending , point.Y ascending
select point;
int[,] sortedTime = new int[5,2];
int index = 0;
foreach (var testPoint in sorted)
{
Point aPoint = (Point) testPoint;
sortedTime.SetValue(aPoint.X, index, 0);
sortedTime.SetValue(aPoint.Y, index, 1);
index++;
}
It looks like you might just be overthinking things. If you want to keep the points together, and sort by the first column, for instance, just omit the second Enumerable.Range and assign the values by hand:
int[,] time = new int[5,2]{{0,4},{1,5},{5,10},{3,4},{0,2}};
var sorted = from x in Enumerable.Range(0, time.GetLength(0))
select new{
X = time[x,0],
Y = time[x,1]
}into point
orderby point.X descending
select point;
As #Haxx points out, just add , point.Y descending to the orderby clause if the order of the second value is also important.
I also think that one should treat this as a collection of rows since you want rows to always stay together.
.NET has the DataTable type for that. E.g.
int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 15, 10 }, { 3, 4 }, { 0, 2 } };
DataTable dt = new DataTable();
dt.Columns.Add("x", System.Type.GetType("System.Int32"));
dt.Columns.Add("y", System.Type.GetType("System.Int32"));
for (int i = 0; i < time.Length / 2; i++)
{
DataRow dr = dt.NewRow();
dr[0] = time[i, 0];
dr[1] = time[i, 1];
dt.Rows.Add(dr);
}
dt.DefaultView.Sort = "x" + " " + "ASC";
dt = dt.DefaultView.ToTable();
Note that I needed to type the table columns. Otherwise you'll get an alphabetical sort. I changed one of your numbers to 15 to demonstrate that the sort works on the integers (15>3, but alphabetically "15"<"3"). If you really want it back as a 2D array, see the first answer.
The fastest method would be to take implementation of some sorting algorithm like Quicksort and modify it to only use the Compare(i, j) and Swap(i, j) functions.
Then you can implement these functions for your multidimensional array and sort it in place.
Here is a working implementation:
public static void Main() {
int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 5, 10 }, { 3, 4 }, { 0, 2 } };
DoSort(time);
}
public static void DoSort(int[,] data) {
Func<int, int, int> comparer = (i, j) => {
int s1 = Math.Sign(data[i, 0] - data[j, 0]);
if (s1 != 0) {
return s1;
}
int s2 = Math.Sign(data[i, 1] - data[j, 1]);
return s2;
};
Action<int, int> swapper = (i, j) => {
var tmp0 = data[i, 0];
var tmp1 = data[i, 1];
data[i, 0] = data[j, 0];
data[i, 1] = data[j, 1];
data[j, 0] = tmp0;
data[j, 1] = tmp1;
};
int length = data.GetLength(0);
Quicksort(comparer, swapper, 0, length - 1);
}
public static void Quicksort(Func<int, int, int> comparer, Action<int, int> swapper, int left, int right) {
int i = left, j = right;
int pivotIdx = (left + right) / 2;
while (i <= j) {
while (comparer(i, pivotIdx) < 0) {
i++;
}
while (comparer(j, pivotIdx) > 0) {
j--;
}
if (i <= j) {
swapper(i, j);
i++;
j--;
}
}
// Recursive calls
if (left < j) {
Quicksort(comparer, swapper, left, j);
}
if (i < right) {
Quicksort(comparer, swapper, i, right);
}
}
}
This code sorts the array in-place so you need no additional memory and in the end you get a sorted multidimensional array.
Assuming:
1. You want to keep the items paired, e.g. want to treat {0, 4} as one pair, {1, 5} as another pair.
2. The expected result in ascending order is: {{0, 2}, {0, 4}, {1, 5}, {3, 4}, {5, 10}}.
As suggested by BTownTKD, strongly recommend to use some class/struct to represent your pair instead of using multidimensional array. You can use a list/array of either of the following:
Tuple<int, int>
KeyValuePair<int, int>
your own struct IntPair, having two properties X and Y.
This will not only help you to sort, but also to do further manipulations easily. Use multidimensional array only if you have a very specific need to.
Here's sample code using Tuple:
List<Tuple<int, int>> time = new List<Tuple<int, int>>(){
new Tuple<int, int>(0,4),
new Tuple<int, int>(1,5),
new Tuple<int, int>(5,10),
new Tuple<int, int>(3,4),
new Tuple<int, int>(0,2)
};
//Sort Ascending
time.Sort((first, second) =>
{
var item1Compare = first.Item1.CompareTo(second.Item1);
return item1Compare == 0 ? first.Item2.CompareTo(second.Item2) : item1Compare;
});
//Sort Descending
/*time.Sort((first, second) =>
{
var item1Compare = second.Item1.CompareTo(first.Item1);
return item1Compare == 0 ? second.Item2.CompareTo(first.Item2) : item1Compare;
});*/
Related
I need to write a method to find the commons between 2 arrays in C# but the thing is I can't convert my python logic from the past to C#
it used to be like this in python:
def commonfinder(list1, list2):
commonlist = []
for x in list1:
for y in list2:
if x==y:
commonlist.append(x)
return commonlist
but when I tried to convert it to C#:
public int [] Commons(int[] ar1, int[] ar2)
{
int commoncount;
int[] Commonslist = new int[commoncount];
foreach (int x in ar1)
{
foreach (int y in ar2)
{
if (x == y)
{
commoncount++;
// here I should add x to Commonlist
}
}
}
return Commonslist;
}
I couldn't find any method or functions that would append x to my Commonlist
and ofc I got a lot of errors I couldn't solve
can I get a tip?
Your original algorithm has O(n * m) time complexity, which can be too long:
imagine that you have lists of 1 million items each (1 trillion compares to perform). You can implement a better code with O(n + m) complexity only:
Code: (let's generalize the problem)
using System.Linq;
...
public static T[] CommonFinder<T>(IEnumerable<T> left,
IEnumerable<T> right,
IEqualityComparer<T> comparer = null) {
if (null == left || null == right)
return new T[0]; // Or throw ArgumentNullException exception
comparer = comparer ?? EqualityComparer<T>.Default;
Dictionary<T, int> dict = right
.GroupBy(item => item)
.ToDictionary(group => group.Key, group => group.Count());
List<T> result = new List<T>();
foreach (T item in left)
if (dict.TryGetValue(item, out int count)) {
result.Add(item);
if (count <= 1)
dict.Remove(item);
else
dict[item] = count - 1;
}
return result.ToArray();
}
Demo:
int[] left = new int[] { 1, 2, 3, 4, 5 };
int[] right = new int[] { 0, 3, 2, 6, 9};
var common = CommonFinder(left, right);
Console.WriteLine(string.Join(", ", common));
Outcome:
2, 3
Note: What I understood is you want a method that takes 2 int arrays and yields 1 int array as the output with the unique intersecting values.
You can use HashSet to speed up to insert and lookup time (amortized O(1)). The running time is O(Max(n,m)) due to us having to go through both the entire arrays (separately). In terms of memory, O(Min(n,m)) because we select the smaller array at the beginning to populate the set and for the rest of the logic naturally won't have more elements than the smaller array because it is the intersect.
The Main method shows you how to utilize the method. CommonIntegers has the logic which you seek.
using System;
using System.Collections.Generic;
using System.Linq;
namespace TestCode.StackOverflow
{
public class So66935672
{
public static void Main(string[] args)
{
int[] intArray1 = new int[] { 9, 9, 1, 3, 5, 6, 10, 9 };
int[] intArray2 = new int[] { 19, 17, 16, 5, 1, 6 };
Console.Write(
CommonIntegers(intArray1, intArray2)
.Select(i => $"{i}, ")
.Aggregate(string.Empty, string.Concat));
}
private static int[] CommonIntegers(int[] intArray1, int[] intArray2)
{
if (intArray1 == null || intArray1.Length == 0
|| intArray2 == null || intArray2.Length == 0)
{
return Array.Empty<int>();
}
var primaryArraySet = new HashSet<int>(); // Contains the unique values from the shorter array
var intersectSet = new HashSet<int>(); // Contains unique values found in both arrays
int[] secondarySet;
// Fill primary set
if (intArray1.Length > intArray2.Length)
{
foreach (var i in intArray2)
primaryArraySet.Add(i);
secondarySet = intArray1;
}
else
{
foreach (var i in intArray1)
primaryArraySet.Add(i);
secondarySet = intArray2;
}
// Fill intersect array
foreach (var i in secondarySet)
if (primaryArraySet.Contains(i))
intersectSet.Add(i);
return intersectSet.ToArray();
}
}
}
You can try this one:
static List<int> CommonFinder(List<int> list1, List<int> list2)
{
List<int> commonList = new List<int>();
foreach (int x in list1)
foreach (int y in list2)
if (x == y)
commonList.Add(x);
return commonList;
}
static void Main()
{
List<int> list1 = new List<int> { 1, 2, 3 };
List<int> list2 = new List<int> { 2, 3, 4};
var common = CommonFinder(list1, list2);
Console.WriteLine(string.Join(", ", common));
}
I have some code to sort an array into ascending order
int[] array = new int[] { 4, 3, 5, 1 };
var result = array.GroupBy(x => x)
.OrderBy(g => g.Count())
.ThenBy(g => g.Key)
.SelectMany(g => g);
I would like to be able to count the number of steps required to complete the sort.
The specific question I am trying to solve is this:
You are given an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates. You are allowed to swap any two elements. You need to find the minimum number of swaps required to sort the array in ascending order.
Can I find the number of swaps used by LINQ?
Is it possible to get this?
So for example if the query had to swap 4 with 1 to get 1,3,5,4 then 5 with 4 to get 1,3,4,5 then this would be 2 steps.
This is how I came up. I couldn't find the way using it with LINQ however with our own Sorting Algorithm. I did something like this:
static void Main(string[] args)
{
ObservableCollection<int> array = new ObservableCollection<int>() {4,3,1,5 };
int steps = 0;
array.CollectionChanged+= (sender, e) =>
{
Console.WriteLine($"{e.Action} : {string.Join(",", array) }" );
steps++;
};
bool didSwap;
do
{
didSwap = false;
for (int i = 0; i < array.Count - 1; i++)
{
if (array[i] > array[i + 1])
{
int temp = array[i + 1];
array[i + 1] = array[i];
array[i] = temp;
didSwap = true;
}
}
} while (didSwap);
Console.WriteLine("Sorted Result :");
foreach(var item in array)
{
Console.WriteLine(item);
}
Console.WriteLine($"Total Swapps {steps / 2}");
Console.ReadLine();
}
This is the output:
I have a script that takes an int[] array, converts it to a list and removes all further occurrences of the integers that already occurred at least 2 times.
The problem I have is that when it gets into the loop where I am checking the count of each integers occurrences, I am getting stuck in a loop.
EDIT: "What I left out was that the list has to remain in its original order so that excess numbers are removed from top down. Sorry if that confused those who already answered!
I thought that the changed number of the occursintegerOccurrence would act as a change of count for the while loop.
Any ideas on what I'm missing here? Aside from any discernible skill.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
public class Kata
{
public static void Main()
{
int[] arr = new int[] {1, 2, 1, 4, 5, 1, 2, 2, 2};
int occurrenceLimit = 2;
var intList = arr.ToList();
for (int i = 0; i < intList.Count; i++)
{
var occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);
do
{
occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);
foreach (var x in intList)
{
Console.WriteLine(x);
intList.Remove(intList.LastIndexOf(occurrenceLimit));
// Tried changing the count here too
occursintegerOccurrence = intList.Count(n => n == occurrenceLimit);
}
} while (occursintegerOccurrence > occurrenceLimit);
}
}
}
Here's a fairly concise version, assuming that you want to remove all instances of integers with a count in excess of 2, leaving the remainder of the bag in its original sequence, with preference to retention traversing from left to right:
int[] arr = new int[] {1, 2, 1, 4, 5, 1, 2, 2, 2};
var ints = arr.Select((n, idx) => new {n, idx})
.GroupBy(x => x.n)
.SelectMany(grp => grp.Take(2))
.OrderBy(x => x.idx)
.Select(x => x.n)
.ToList();
Result:
1, 2, 1, 4, 5, 2
It works by using the index overload of Select to project an anonymous Tuple and carrying through the original order to allow re-ordering at the end.
The cause of the endless loop is the line
intList.Remove(intList.LastIndexOf(occurrenceLimit));
..you are removing the value equals to the last occurence in the list of the occurrenceLimit value(=2), that it is "8" (the last index of the array counting from 0).
Since "8" it isn't present in the list, you don't remove anything and the loop permanence test doesn't ever change and so it is always verified and the loop never ends..
This method works for any values of occurrenceLimit but I think that the solution of StuartLC is better..
int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int?[] arr2 = new int?[arr.Length];
arr2.ToList().ForEach(i => i = null);
int occurrenceLimit = 2;
var ints = arr.GroupBy(x => x).Select(x => x.Key).ToList();
ints.ForEach(i => {
int ndx = 0;
for (int occ = 0; occ < occurrenceLimit; occ++){
ndx = arr.ToList().IndexOf(i, ndx);
if (ndx < 0) break;
arr2[ndx++] = i;
}
});
List<int?> intConverted = arr2.ToList();
intConverted.RemoveAll(i => i.Equals(null));
this may help you
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int occurrenceLimit = 2;
var newList = new List<Vm>();
var result=new List<Vm>();
for (int i = 0; i < arr.Length; i++)
{
var a = new Vm {Value = arr[i], Index = i};
result.Add(a);
}
foreach (var item in result.GroupBy(x => x.Value))
{
newList.AddRange(item.Select(x => x).Take(occurrenceLimit));
}
Console.WriteLine(string.Join(",",newList.OrderBy(x=>x.Index).Select(a=>a.Value)));
Console.ReadKey();
}
}
public class Vm
{
public int Value { get; set; }
public int Index { get; set; }
}
}
I did the following:
I created a Vm class with 2 props (Value and Index), in order to save the index of each value in the array.
I goup by value and take 2 ccurence of each values.
I order the result list base on the initial index.
It can be done by defining your own enumerator method, which will count already happened occurrences:
using System;
using System.Collections.Generic;
using System.Linq;
static class Test {
static IEnumerable<int> KeepNoMoreThen(this IEnumerable<int> source, int limit) {
Dictionary<int, int> counts = new Dictionary<int, int>();
foreach(int current in source) {
int count;
counts.TryGetValue(current, out count);
if(count<limit) {
counts[current]=count+1;
yield return current;
}
}
}
static void Main() {
int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int occurrenceLimit = 2;
List<int> result = arr.KeepNoMoreThen(occurrenceLimit).ToList();
result.ForEach(Console.WriteLine);
}
}
var removal = arr.GroupBy (a =>a ).Where (a =>a.Count()>2).Select(a=>a.Key).ToArray();
var output = arr.Where (a =>!removal.Contains(a)).ToList();
removal is an array of the items which appear more than twice.
output is the original list with those items removed.
[Update -- Just discovered that this handles the problem as originally specified, not as later clarified)
A single pass over the input array maintaining occurrence count dictionary should do the job in O(N) time:
int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int occurrenceLimit = 2;
var counts = new Dictionary<int, int>();
var resilt = arr.Where(n =>
{
int count;
if (counts.TryGetValue(n, out count) && count >= occurrenceLimit) return false;
counts[n] = ++count;
return true;
}).ToList();
Your code is stuck in an infinite loop because you are using List.Remove(), and the Remove() method removes an item by matching against the item you pass in. But you are passing in a list index instead of a list item, so you are getting unintended results. What you want to use is List.RemoveAt(), which removes an item by matching against the index.
So your code is stuck in an infinite loop because intList.LastIndexOf(occurrenceLimit) is returning 8, then Remove() looks for the item 8 in the list, but it doesn't find it so it returns false and your code continues to run. Changing this line:
intList.Remove(intList.LastIndexOf(occurrenceLimit));
to
intList.RemoveAt(intList.LastIndexOf(occurrenceLimit));
will "fix" your code and it will no longer get stuck in an infinite loop. It would then have the expected behavior of throwing an exception because you are modifying a collection that you are iterating through in a foreach.
As for your intended solution, I have rewritten your code with some changes, but keeping most of your code there instead of rewriting it entirely using LINQ or other magic. You had some issues:
1) You were counting the number of times occurenceLimit was found in the list, not the number of times an item was found in the list. I fixed this by comparing against intList[i].
2) You were using Remove() instead of RemoveAt().
3) Your foreach and do while need some work. I went with a while to simplify the initial case, and then used a for loop so I can modify the list (you cannot modify a list that you are iterating over in a foreach). In this for loop I iterate to the number of occurences - occurenceLimit to remove all but the first occurenceLimit number of them -- your initial logic was missing this and if your code worked as intended you would have removed every single one.
static void Main(string[] args)
{
int[] arr = new int[] { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
int occurrenceLimit = 2;
var intList = arr.ToList();
// Interestingly, this `.Count` property updates during the for loop iteration,
// so even though we are removing items inside this `for` loop, we do not run off the
// end of the list as Count is constantly updated.
// Doing `var count = intList.Count`, `for (... i < count ...)` would blow up.
for (int i = 0; i < intList.Count; i++)
{
// Find the number of times the item at index `i` occurs
int occursintegerOccurrence = intList.Count(n => n == intList[i]);
// If `occursintegerOccurrence` is greater than `occurenceLimit`
// then remove all but the first `occurrenceLimit` number of them
while (occursintegerOccurrence > occurrenceLimit)
{
// We are not enumerating the list, so we can remove items at will.
for (var ii = 0; ii < occursintegerOccurrence - occurrenceLimit; ii++)
{
var index = intList.LastIndexOf(intList[i]);
intList.RemoveAt(index);
}
occursintegerOccurrence = intList.Count(n => n == intList[i]);
}
}
// Verify the results
foreach (var item in intList)
{
Console.Write(item + " ");
}
Console.WriteLine(Environment.NewLine + "Done");
Console.ReadLine();
}
Here's a pretty optimal solution:
var list = new List<int> { 1, 2, 1, 4, 5, 1, 2, 2, 2 };
var occurrenceLimit = 2;
list.Reverse(); // Reverse list to make sure we remove LAST elements
// We will store count of each element's occurence here
var counts = new Dictionary<int, int>();
for (int i = list.Count - 1; i >= 0; i--)
{
var elem = list[i];
if (counts.ContainsKey(elem)) // If we already faced this element we increment the number of it's occurencies
{
counts[elem]++;
if (counts[elem] > occurrenceLimit) // If it occured more then 2 times we remove it from the list
list.RemoveAt(i);
}
else
counts.Add(elem, 1); // We haven't faced this element yet so add it to the dictionary with occurence count of 1
}
list.Reverse(); // Again reverse list
The key feature with list is that you have to traverse it backwards to have a possibility to remove items. When you traverse it as usual it will throw you an exception that explains that the list cannot modified. But when you are going backwards you can remove elements as you wish as this won't affect your further operations.
I have a list of list of integers. How do I filter it of the list of integer inside list is empty.
For example:- L = [[0,1,2], [], [1], [1,2,3]]. How do I filter it to get L = [[0,1,2], [1], [1,2,3]] using linq?
Here [0,1,2] is list of integers.
This is related to my previous question. I have a recursive function which returns a list of list of integers and I need to filter out the empty lists.
int [] num_list = new int[10]{2, 3, 5, 9, 14, 19, 23, 45, 92, 100};
public List<List<int>> find_solutions(int n, int t, int w)
{
if (n == 2)
{
List<int> s = new List<int>();
for (var i=0; i <= t; i++)
{
if (i * num_list[1] + (t - i) * num_list[0] == w)
{
s.Add(i);
s.Add(t - i);
}
}
return new List<List<int>> { s };
}
List<List<int>> f = new List<List<int>>();
List<List<int>> temp_list = new List<List<int>>();
for (int i=0; i <= Math.Min(t, w/num_list[n-1]); i++)
{
temp_list = find_solutions(n - 1, t - i, w - i * num_list[n - 1]);
// I strongly believe that i am getting empty list
// and I should filter out empty list form temp_list
// and I need to insert 'i' to each list inside list
foreach(List<int> c in temp_list)
{
c.Insert(0, i);
}
f.addRange(temp_list);
}
return f;
}
int[][] allLists = new int[][] { new int[] { 0, 1, 2 }, new int[] { },
new int[] { 1 }, new int[] { 1, 2, 3 } };
int[][] nonEmtpy = allLists.Where(list => list.Any()).ToArray();
You can use Where and Any to filter out any empty entries.
var listOfLists = L; //To use a better name for L
var nonEmptyLists = listOfLists.Where(innerList => innerList.Any());
You can iterate over this, and/or call ToList or ToArray if necessary
You can achieve this in following ways:
L.Where(p=>p.Any()).ToList();
L.Where(p=>p.Count > 0).ToList();
The Count property is optimized for ICollection<T> where T is a type. Any() has to build an enumerator. So the Count property is faster than Any() method
You can filter using Where() and asking for Count:
var list = new List<List<int>>();
...
list = list.Where(l => l.Count > 0).ToList();
Like this?
L.Where(i => i.Count() > 0).ToList()
I have a function that is simply meant to print out a dictionary of frequent item sets in an easy-to-understand fashion. The goal is to order first by the size of the dictionary key and then by the lexicographical order of a list of numbers. The issue arises in the ThenBy statement as the commented out "hello" will get printed indefinitely. If I change the ThenBy to not use the comparer and simply use another int or string value, it works fine, so I'm clearly doing something wrong.
public static void printItemSets(Dictionary<List<int>, int> freqItemSet)
{
List<KeyValuePair<List<int>, int>> printList = freqItemSet.ToList();
printList = printList.OrderBy(x => x.Key.Count)
.ThenBy(x => x.Key, new ListComparer())
.ToList();
}
The code for the ListComparer is as follows:
public class ListComparer: IEqualityComparer<List<int>>, IComparer<List<int>>
{
public int Compare(List<int> a, List<int> b)
{
int larger = a.Count > b.Count ? 1: -1;
for (int i = 0; i < a.Count && i < b.Count; i++)
{
if (a[i] < b[i])
{
return -1;
}
else if (a[i] > b[i])
{
return 1;
}
else { }
}
return larger;
}
}
VERY simple test case:
int[] a = {1, 3, 5};
int[] b = { 2, 3, 5 };
int[] c = { 1, 2, 3, 5 };
int[] d = { 2, 5 };
int[] e = { 1, 3, 4 };
List<int> aL = a.ToList<int>();
List<int> bL = b.ToList<int>();
List<int> cL = c.ToList<int>();
List<int> dL = d.ToList<int>();
List<int> eL = e.ToList<int>();
Dictionary<List<int>, int> test = new Dictionary<List<int>, int>(new ListComparer());
test.Add(aL, 1);
test.Add(bL, 1);
test.Add(cL, 1);
test.Add(dL, 1);
test.Add(eL, 1);
The issue is that ListComparer is not checking if the arrays are the same. The same array is being passed in twice for both x and y. Checking if x and y are equal will resolve your issue.
Your comparer doesn't handle equal items. If the items are equal the order of the two items is what determines which is considered "larger". The comparer is thus not "reflexive". Being reflexive is a property sorting algorithms rely on.
The first line should be var larger = a.Count.CompareTo(b.Count); instead, so that truly equal lists will return 0 rather than either -1 or 1.