using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using U.ListOperations.ListSort;
using U.ListOperations.UStats;

namespace U.ListOperations
{
    public class UList
    {
        // newList
        public static List<string> newList(string str1, string str2) { return new List<string>() { str1, str2 }; }
        public static List<string> newList(string str1, string str2, string str3) { return new List<string>() { str1, str2, str3 }; }
        public static List<string> newList(string str1, string str2, string str3, string str4) { return new List<string>() { str1, str2, str3, str4 }; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5) { return new List<string>() { str1, str2, str3, str4, str5}; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5, string str6) { return new List<string>() { str1, str2, str3, str4, str5, str6}; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5, string str6, string str7) { return new List<string>() { str1, str2, str3, str4, str5, str6, str7}; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5, string str6, string str7, string str8) { return new List<string>() { str1, str2, str3, str4, str5, str6, str7, str8}; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5, string str6, string str7, string str8, string str9) { return new List<string>() { str1, str2, str3, str4, str5, str6, str7, str8, str9 }; }
        public static List<string> newList(string str1, string str2, string str3, string str4, string str5, string str6, string str7, string str8, string str9, string str10) { return new List<string>() { str1, str2, str3, str4, str5, str6, str7, str8, str9, str10 }; }
        public static List<double> newList(double dbl1, double dbl2) { return new List<double>() { dbl1, dbl2 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3) { return new List<double>() { dbl1, dbl2, dbl3 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4) { return new List<double>() { dbl1, dbl2, dbl3, dbl4 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5, double dbl6) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5, dbl6 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5, double dbl6, double dbl7) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5, dbl6, dbl7 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5, double dbl6, double dbl7, double dbl8) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5, dbl6, dbl7, dbl8 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5, double dbl6, double dbl7, double dbl8, double dbl9) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5, dbl6, dbl7, dbl8, dbl9 }; }
        public static List<double> newList(double dbl1, double dbl2, double dbl3, double dbl4, double dbl5, double dbl6, double dbl7, double dbl8, double dbl9, double dbl10) { return new List<double>() { dbl1, dbl2, dbl3, dbl4, dbl5, dbl6, dbl7, dbl8, dbl9, dbl10 }; }
        public static List<int> newList(int int1, int int2) { return new List<int>() { int1, int2 }; }
        public static List<int> newList(int int1, int int2, int int3) { return new List<int>() { int1, int2, int3 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4) { return new List<int>() { int1, int2, int3, int4 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5) { return new List<int>() { int1, int2, int3, int4, int5 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5, int int6) { return new List<int>() { int1, int2, int3, int4, int5, int6 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5, int int6, int int7) { return new List<int>() { int1, int2, int3, int4, int5, int6, int7 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5, int int6, int int7, int int8) { return new List<int>() { int1, int2, int3, int4, int5, int6, int7, int8 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5, int int6, int int7, int int8, int int9) { return new List<int>() { int1, int2, int3, int4, int5, int6, int7, int8, int9 }; }
        public static List<int> newList(int int1, int int2, int int3, int int4, int int5, int int6, int int7, int int8, int int9, int int10) { return new List<int>() { int1, int2, int3, int4, int5, int6, int7, int8, int9, int10 }; }


        // type
        public static List<string> toString(List<double> list) { List<string> l = new List<string>(); for (int i = 0; i < list.Count; i++) { l.Add(list[i].ToString()); } return l; }

        // indexList
        public static List<int> indexList(int n) { List<int> list = new List<int>(); for (int i = 0; i < n; i++) { list.Add(i); } return list; }

        // sameValues
        public static List<T> sameValues<T>(T val, int n) { List<T> list = new List<T>(); for (int i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<string> sameValues(string val, int n) { List<string> list = new List<string>(); for (int i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<double> sameValues(double val, int n) { List<double> list = new List<double>(); for (int i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<int> sameValues(int val, int n) { List<int> list = new List<int>(); for (int i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<List<string>> sameValues(string val, int nRows, int nCols) { List<List<string>> m = new List<List<string>>(); for (int i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }
        public static List<List<double>> sameValues(double val, int nRows, int nCols) { List<List<double>> m = new List<List<double>>(); for (int i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }
        public static List<List<int>> sameValues(int val, int nRows, int nCols) { List<List<int>> m = new List<List<int>>(); for (int i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }
        public static List<T> sameValues<T>(T val, long n) { List<T> list = new List<T>(); for (long i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<string> sameValues(string val, long n) { List<string> list = new List<string>(); for (long i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<double> sameValues(double val, long n) { List<double> list = new List<double>(); for (long i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<int> sameValues(int val, long n) { List<int> list = new List<int>(); for (long i = 0; i < n; i++) { list.Add(val); } return list; }
        public static List<List<string>> sameValues(string val, long nRows, long nCols) { List<List<string>> m = new List<List<string>>(); for (long i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }
        public static List<List<double>> sameValues(double val, long nRows, long nCols) { List<List<double>> m = new List<List<double>>(); for (long i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }
        public static List<List<int>> sameValues(int val, long nRows, long nCols) { List<List<int>> m = new List<List<int>>(); for (long i = 0; i < nRows; i++) { m.Add(sameValues(val, nCols)); } return m; }

        // clone
        public static List<string> clone(List<string> list) { List<string> l = new List<string>(); foreach (string d in list) { l.Add(d); } return l; }
        public static List<double> clone(List<double> list) { List<double> l = new List<double>(); foreach (double d in list) { l.Add(d); } return l; }
        public static List<int> clone(List<int> list) { List<int> l = new List<int>(); foreach (int d in list) { l.Add(d); } return l; }
        public static List<long> clone(List<long> list) { List<long> l = new List<long>(); foreach (int d in list) { l.Add(d); } return l; }
        public static List<List<string>> clone(List<List<string>> table) { List<List<string>> t = new List<List<string>>(); foreach (List<string> list in table) { t.Add(clone(list)); } return t; }
        public static List<List<double>> clone(List<List<double>> table) { List<List<double>> t = new List<List<double>>(); foreach (List<double> list in table) { t.Add(clone(list)); } return t; }
        public static List<List<int>> clone(List<List<int>> table) { List<List<int>> t = new List<List<int>>(); foreach (List<int> list in table) { t.Add(clone(list)); } return t; }
        public static List<List<long>> clone(List<List<long>> table) { List<List<long>> t = new List<List<long>>(); foreach (List<long> list in table) { t.Add(clone(list)); } return t; }
        
        // absolute clone
        public static List<double> cloneAbsolute(List<double> list) { List<double> l = new List<double>(); foreach (double d in list) { l.Add(Math.Abs(d)); } return l; }
        public static List<int> cloneAbsolute(List<int> list) { List<int> l = new List<int>(); foreach (int d in list) { l.Add(Math.Abs(d)); } return l; }
        public static List<long> cloneAbsolute(List<long> list) { List<long> l = new List<long>(); foreach (int d in list) { l.Add(Math.Abs(d)); } return l; }
        // sorted clone
        public static List<double> sortedClone(List<double> list, bool ascending, bool absolute) { List<double> c; if (absolute) { c = cloneAbsolute(list); } else { c = clone(list); } c.Sort(); if (!ascending) { c.Reverse(); } return c; }
        public static List<int> sortedClone(List<int> list, bool ascending, bool absolute) { List<int> c; if (absolute) { c = cloneAbsolute(list); } else { c = clone(list); } c.Sort(); if (!ascending) { c.Reverse(); } return c; }
        public static List<long> sortedClone(List<long> list, bool ascending, bool absolute) { List<long> c; if (absolute) { c = cloneAbsolute(list); } else { c = clone(list); } c.Sort(); if (!ascending) { c.Reverse(); } return c; }

        // sort
        public static List<double> sort(List<double> list, bool ascending) { list.Sort(); if (ascending) { return list; } list.Reverse(); return list; }
        public static List<int> sort(List<int> list, bool ascending) { list.Sort(); if (ascending) { return list; } list.Reverse(); return list; }
        public static List<long> sort(List<long> list, bool ascending) { list.Sort(); if (ascending) { return list; } list.Reverse(); return list; }

        // distinct
        public static List<T> distinct<T>(List<T> list) { return list.Distinct().ToList(); }
        public static List<string> distinct(List<string> list) { return list.Distinct().ToList(); }
        public static List<double> distinct(List<double> list) { return list.Distinct().ToList(); }
        public static List<int> distinct(List<int> list) { return list.Distinct().ToList(); }
        public static List<long> distinct(List<long> list) { return list.Distinct().ToList(); }
        
        // Basic math operations
        public static List<double> add(List<double> list, double constant) { List<double> l = new List<double>(); foreach (double v in list) { l.Add(v + constant); } return l; }
        public static List<int> add(List<int> list, int constant) { List<int> l = new List<int>(); foreach (int v in list) { l.Add(v + constant); } return l; }
        public static List<long> add(List<long> list, long constant) { List<long> l = new List<long>(); foreach (long v in list) { l.Add(v + constant); } return l; }
        public static List<double> subtract(List<double> list, double constant) { List<double> l = new List<double>(); foreach (double v in list) { l.Add(v - constant); } return l; }
        public static List<int> subtract(List<int> list, int constant) { List<int> l = new List<int>(); foreach (int v in list) { l.Add(v - constant); } return l; }
        public static List<long> subtract(List<long> list, long constant) { List<long> l = new List<long>(); foreach (long v in list) { l.Add(v - constant); } return l; }
        public static List<double> multiply(List<double> list, double constant) { List<double> l = new List<double>(); foreach (double v in list) { l.Add(v * constant); } return l; }
        public static List<int> multiply(List<int> list, int constant) { List<int> l = new List<int>(); foreach (int v in list) { l.Add(v * constant); } return l; }
        public static List<long> multiply(List<long> list, long constant) { List<long> l = new List<long>(); foreach (long v in list) { l.Add(v * constant); } return l; }
        public static List<double> divide(List<double> list, double constant) { List<double> l = new List<double>(); foreach (double v in list) { l.Add(v / constant); } return l; }
        public static List<int> divide(List<int> list, int constant) { List<int> l = new List<int>(); foreach (int v in list) { l.Add(v / constant); } return l; }
        public static List<long> divide(List<long> list, long constant) { List<long> l = new List<long>(); foreach (long v in list) { l.Add(v / constant); } return l; }

        // Equals
        public static bool equals<T>(List<T> list1, List<T> list2) { if (list1.Count != list2.Count) { return false; } for (int i = 0; i < list1.Count; i++) { if (!list1[i].Equals(list2[i])) { return false; } } return true; }
        public static bool equals(List<string> list1, List<string> list2) { if (list1.Count != list2.Count) { return false; } for (int i = 0; i < list1.Count; i++) { if (!list1[i].Equals(list2[i])) { return false; } } return true; }
        public static bool equals(List<double> list1, List<double> list2) { if (list1.Count != list2.Count) { return false; } for (int i = 0; i < list1.Count; i++) { if (!list1[i].Equals(list2[i])) { return false; } } return true; }
        public static bool equals(List<int> list1, List<int> list2) { if (list1.Count != list2.Count) { return false; } for (int i = 0; i < list1.Count; i++) { if (!list1[i].Equals(list2[i])) { return false; } } return true; }

        // Intersection
        public static List<T> intersection<T>(List<T> list1, List<T> list2) { List<T> l = new List<T>(); foreach (T v in list1) { if (list2.Contains(v)) { l.Add(v); } } return l; }
        public static List<string> intersection(List<string> list1, List<string> list2) { List<string> l = new List<string>(); foreach (string v in list1) { if (list2.Contains(v)) { l.Add(v); } } return l; }
        public static List<double> intersection(List<double> list1, List<double> list2) { List<double> l = new List<double>(); foreach (double v in list1) { if (list2.Contains(v)) { l.Add(v); } } return l; }
        public static List<int> intersection(List<int> list1, List<int> list2) { List<int> l = new List<int>(); foreach (int v in list1) { if (list2.Contains(v)) { l.Add(v); } } return l; }

        // Union
        public static List<T> union<T>(List<T> list1, List<T> list2) { List<T> l = new List<T>(); l.AddRange(list1); l.AddRange(list2); return distinct(l); }
        public static List<string> union(List<string> list1, List<string> list2) { List<string> l = new List<string>(); l.AddRange(list1); l.AddRange(list2); return distinct(l); }
        public static List<double> union(List<double> list1, List<double> list2) { List<double> l = new List<double>(); l.AddRange(list1); l.AddRange(list2); return distinct(l); }
        public static List<int> union(List<int> list1, List<int> list2) { List<int> l = new List<int>(); l.AddRange(list1); l.AddRange(list2); return distinct(l); }

        // Set Minus
        public static List<T> setDifference<T>(List<T> list, List<T> listToSubtract) { List<T> l = new List<T>(); foreach (T v in list) { if (!listToSubtract.Contains(v)) { l.Add(v); } } return l; }
        public static List<string> setDifference(List<string> list, List<string> listToSubtract) { List<string> l = new List<string>(); foreach (string v in list) { if (!listToSubtract.Contains(v)) { l.Add(v); } } return l; }
        public static List<double> setDifference(List<double> list, List<double> listToSubtract) { List<double> l = new List<double>(); foreach (double v in list) { if (!listToSubtract.Contains(v)) { l.Add(v); } } return l; }
        public static List<int> setDifference(List<int> list, List<int> listToSubtract) { List<int> l = new List<int>(); foreach (int v in list) { if (!listToSubtract.Contains(v)) { l.Add(v); } } return l; }

        // isSubsetOf
        public static bool isSubsetOf<T>(List<T> subset, List<T> set) { if (subset.Count == 0 && set.Count == 0) { return true; } foreach (T item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(List<string> subset, List<string> set) { if (subset.Count == 0 && set.Count == 0) { return true; } foreach (string item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(List<double> subset, List<double> set) { if (subset.Count == 0 && set.Count == 0) { return true; } foreach (double item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(List<int> subset, List<int> set) { if (subset.Count == 0 && set.Count == 0) { return true; } foreach (int item in subset) { if (!set.Contains(item)) { return false; } } return true; }

        // getSubset
        public static List<T> getSubset<T>(List<T> set, List<int> subsetItemIds) { List<T> subset = new List<T>(); foreach (int id in subsetItemIds) { subset.Add(set[id]); } return subset; }
        public static List<string> getSubset(List<string> set, List<int> subsetItemIds) { List<string> subset = new List<string>(); foreach (int id in subsetItemIds) { subset.Add(set[id]); } return subset; }
        public static List<double> getSubset(List<double> set, List<int> subsetItemIds) { List<double> subset = new List<double>(); foreach (int id in subsetItemIds) { subset.Add(set[id]); } return subset; }
        public static List<int> getSubset(List<int> set, List<int> subsetItemIds) { List<int> subset = new List<int>(); foreach (int id in subsetItemIds) { subset.Add(set[id]); } return subset; }
        public static List<T> getFirstItems<T>(List<T> set, int nbItems) { List<T> subset = new List<T>(); for (int i = 0; i < nbItems; i++) { subset.Add(set[i]); } return subset; }
        public static List<string> getFirstItems(List<string> set, int nbItems) { List<string> subset = new List<string>(); for (int i = 0; i < nbItems; i++) { subset.Add(set[i]); } return subset; }
        public static List<double> getFirstItems(List<double> set, int nbItems) { List<double> subset = new List<double>(); for (int i = 0; i < nbItems; i++) { subset.Add(set[i]); } return subset; }
        public static List<int> getFirstItems(List<int> set, int nbItems) { List<int> subset = new List<int>(); for (int i = 0; i < nbItems; i++) { subset.Add(set[i]); } return subset; }
        public static List<T> getLastItems<T>(List<T> set, int nbItems) { List<T> subset = new List<T>(); for (int i = set.Count - nbItems; i < set.Count; i++) { subset.Add(set[i]); } return subset; }
        public static List<string> getLastItems(List<string> set, int nbItems) { List<string> subset = new List<string>(); for (int i = set.Count - nbItems; i < set.Count; i++) { subset.Add(set[i]); } return subset; }
        public static List<double> getLastItems(List<double> set, int nbItems) { List<double> subset = new List<double>(); for (int i = set.Count - nbItems; i < set.Count; i++) { subset.Add(set[i]); } return subset; }
        public static List<int> getLastItems(List<int> set, int nbItems) { List<int> subset = new List<int>(); for (int i = set.Count - nbItems; i < set.Count; i++) { subset.Add(set[i]); } return subset; }

        // from DataTable
        public static List<List<string>> getDtRows(DataTable dataTable, bool includeHeaders) { List<List<string>> lst = new List<List<string>>(); if (includeHeaders) { lst.Add(getDtHeaders(dataTable)); } foreach (DataRow dr in dataTable.Rows) { List<string> row = new List<string>(); foreach (DataColumn dc in dataTable.Columns) { row.Add(dr[dc].ToString()); } lst.Add(row); } return lst; }
        public static List<string> getDtHeaders(DataTable dataTable) { List<string> l = new List<string>(); foreach (DataColumn col in dataTable.Columns) { l.Add(col.ColumnName); } return l; }
        public static List<string> getDtColumnString(DataTable dataTable, int columnNumber) { List<string> l = new List<string>(); for (int i = 0; i < dataTable.Rows.Count; i++) { l.Add(dataTable.Rows[i][columnNumber].ToString()); } return l; }
        public static List<double> getDtColumnDouble(DataTable dataTable, int columnNumber) { List<double> l = new List<double>(); for (int i = 0; i < dataTable.Rows.Count; i++) { l.Add(Convert.ToDouble(dataTable.Rows[i][columnNumber].ToString())); } return l; }
        public static List<short> getDtColumnInt16(DataTable dataTable, int columnNumber) { List<short> l = new List<short>(); for (int i = 0; i < dataTable.Rows.Count; i++) { l.Add(Convert.ToInt16(dataTable.Rows[i][columnNumber].ToString())); } return l; }
        public static List<int> getDtColumnInt32(DataTable dataTable, int columnNumber) { List<int> l = new List<int>(); for (int i = 0; i < dataTable.Rows.Count; i++) { l.Add(Convert.ToInt32(dataTable.Rows[i][columnNumber].ToString())); } return l; }
        public static List<long> getDtColumnInt64(DataTable dataTable, int columnNumber) { List<long> l = new List<long>(); for (int i = 0; i < dataTable.Rows.Count; i++) { l.Add(Convert.ToInt64(dataTable.Rows[i][columnNumber].ToString())); } return l; }

        // to DataTable
        public static DataTable getDt(List<string> headers, List<List<string>> table) { DataTable dt = new DataTable(); foreach (string header in headers) { dt.Columns.Add(header); } if (table.Count == 0) { return dt; } if (table[0].Count != headers.Count) { return null; } foreach (List<string> row in table) { DataRow dr = dt.NewRow(); for (int j = 0; j < row.Count; j++) { dr[j] = row[j]; } dt.Rows.Add(dr); } return dt; }
        public static DataTable getDt(List<string> headers, List<List<double>> table) { DataTable dt = new DataTable(); foreach (string header in headers) { dt.Columns.Add(header, System.Type.GetType("System.Double")); } if (table.Count == 0) { return dt; } if (table[0].Count != headers.Count) { return null; } foreach (List<double> row in table) { DataRow dr = dt.NewRow(); for (int j = 0; j < row.Count; j++) { dr[j] = row[j]; } dt.Rows.Add(dr); } return dt; }
        public static DataTable getDt(List<string> headers, List<List<short>> table) { DataTable dt = new DataTable(); foreach (string header in headers) { dt.Columns.Add(header); } if (table.Count == 0) { return dt; } if (table[0].Count != headers.Count) { return null; } foreach (List<short> row in table) { DataRow dr = dt.NewRow(); for (int j = 0; j < row.Count; j++) { dr[j] = row[j]; } dt.Rows.Add(dr); } return dt; }
        public static DataTable getDt(List<string> headers, List<List<int>> table) { DataTable dt = new DataTable(); foreach (string header in headers) { dt.Columns.Add(header); } if (table.Count == 0) { return dt; } if (table[0].Count != headers.Count) { return null; } foreach (List<int> row in table) { DataRow dr = dt.NewRow(); for (int j = 0; j < row.Count; j++) { dr[j] = row[j]; } dt.Rows.Add(dr); } return dt; }
        public static DataTable getDt(List<string> headers, List<List<long>> table) { DataTable dt = new DataTable(); foreach (string header in headers) { dt.Columns.Add(header); } if (table.Count == 0) { return dt; } if (table[0].Count != headers.Count) { return null; } foreach (List<long> row in table) { DataRow dr = dt.NewRow(); for (int j = 0; j < row.Count; j++) { dr[j] = row[j]; } dt.Rows.Add(dr); } return dt; }
        
        // indexOfMin
        public static int indexOfMin(List<double> list) { double min = double.MaxValue; int x = -1; for (int i = 0; i < list.Count; i++) { if (list[i] < min) { min = list[i]; x = i; } } return x; }
        public static int indexOfMin(List<int> list) { int min = Int32.MaxValue; int x = -1; for (int i = 0; i < list.Count; i++) { if (list[i] < min) { min = list[i]; x = i; } } return x; }
        public static int indexOfMin(List<long> list) { long min = Int64.MaxValue; int x = -1; for (int i = 0; i < list.Count; i++) { if (list[i] < min) { min = list[i]; x = i; } } return x; }

        // toList
        public static List<T> toList<T>(T[] array) { List<T> l = new List<T>(); for (int i = 0; i < array.Length; i++) { l.Add(array[i]); } return l; }
        public static List<string> toList(string[] array) { List<string> l = new List<string>(); for (int i = 0; i < array.Length; i++) { l.Add(array[i]); } return l; }
        public static List<double> toList(double[] array) { List<double> l = new List<double>(); for (int i = 0; i < array.Length; i++) { l.Add(array[i]); } return l; }
        public static List<int> toList(int[] array) { List<int> l = new List<int>(); for (int i = 0; i < array.Length; i++) { l.Add(array[i]); } return l; }

        /*/ getTopIds
        public static List<int> getTopIds(List<int> ids, List<int> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(ids, values); return sortList.getTopIds(ascending, absolute, topN); }
        public static List<int> getTopIds(List<int> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(values); return sortList.getTopIds(ascending, absolute, topN); }
        public static List<int> getTopIds(List<int> ids, List<double> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(ids, values); return sortList.getTopIds(ascending, absolute, topN); }
        public static List<int> getTopIds(List<double> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(values); return sortList.getTopIds(ascending, absolute, topN); }
        public static List<int> getTopIds(List<int> ids, List<long> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(ids, values); return sortList.getTopIds(ascending, absolute, topN); }
        public static List<int> getTopIds(List<long> values, bool ascending, bool absolute, int topN) { SortList sortList = new SortList(values); return sortList.getTopIds(ascending, absolute, topN); }
        //*/
        // Random
        public static List<double> getUniformRandomVector(Random r, int n) { List<double> list = new List<double>(); for (int i = 0; i < n; i++) { list.Add(r.NextDouble()); } return list; }

        /*/ Ranks
        public static List<int> getRanks(List<int> values, bool ascending, bool absolute) { List<int> topIds = new SortList(values).getTopIds(ascending, absolute, values.Count); List<int> ranks = sameValues(-1, values.Count); for (int i = 0; i < topIds.Count; i++) { ranks[topIds[i]] = i; } return ranks; }
        public static List<int> getRanks(List<double> values, bool ascending, bool absolute) { List<int> topIds = new SortList(values).getTopIds(ascending, absolute, values.Count); List<int> ranks = sameValues(-1, values.Count); for (int i = 0; i < topIds.Count; i++) { ranks[topIds[i]] = i; } return ranks; }
        public static List<int> getRanks(List<long> values, bool ascending, bool absolute) { List<int> topIds = new SortList(values).getTopIds(ascending, absolute, values.Count); List<int> ranks = sameValues(-1, values.Count); for (int i = 0; i < topIds.Count; i++) { ranks[topIds[i]] = i; } return ranks; }
        //*/

        // TABLE
        // Nb of items in Lists
        public static int getMaxNbItems(List<List<string>> table) { if (table.Count == 0) { return 0; } int max = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count > max) { max = table[i].Count; } } return max; }
        public static int getMaxNbItems(List<List<int>> table) { if (table.Count == 0) { return 0; } int max = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count > max) { max = table[i].Count; } } return max; }
        public static int getMaxNbItems(List<List<double>> table) { if (table.Count == 0) { return 0; } int max = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count > max) { max = table[i].Count; } } return max; }
        public static int getMaxNbItems(List<List<long>> table) { if (table.Count == 0) { return 0; } int max = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count > max) { max = table[i].Count; } } return max; }
        public static int getMaxNbItems<T>(List<List<T>> table) { if (table.Count == 0) { return 0; } int max = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count > max) { max = table[i].Count; } } return max; }
        public static int getMinNbItems(List<List<string>> table) { if (table.Count == 0) { return 0; } int min = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count < min) { min = table[i].Count; } } return min; }
        public static int getMinNbItems(List<List<int>> table) { if (table.Count == 0) { return 0; } int min = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count < min) { min = table[i].Count; } } return min; }
        public static int getMinNbItems(List<List<double>> table) { if (table.Count == 0) { return 0; } int min = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count < min) { min = table[i].Count; } } return min; }
        public static int getMinNbItems(List<List<long>> table) { if (table.Count == 0) { return 0; } int min = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count < min) { min = table[i].Count; } } return min; }
        public static int getMinNbItems<T>(List<List<T>> table) { if (table.Count == 0) { return 0; } int min = table[0].Count; for (int i = 1; i < table.Count; i++) { if (table[i].Count < min) { min = table[i].Count; } } return min; }
        // transpose
        public static List<List<string>> transpose(List<List<string>> table)
        {
            List<List<string>> t = new List<List<string>>();
            int nbRows = getMaxNbItems(table);
            for (int j = 0; j < nbRows; j++) { t.Add(new List<string>()); }
            for (int i = 0; i < table.Count; i++)
            {
                for (int j = 0; j < table[i].Count; j++)
                {
                    t[j].Add(table[i][j]);
                }
            }
            return t;
        }
        public static List<List<double>> transpose(List<List<double>> table)
        {
            List<List<double>> t = new List<List<double>>();
            int nbRows = getMaxNbItems(table);
            for (int j = 0; j < nbRows; j++) { t.Add(new List<double>()); }
            for (int i = 0; i < table.Count; i++)
            {
                for (int j = 0; j < table[i].Count; j++)
                {
                    t[j].Add(table[i][j]);
                }
            }
            return t;
        }
        public static List<List<int>> transpose(List<List<int>> table)
        {
            List<List<int>> t = new List<List<int>>();
            int nbRows = getMaxNbItems(table);
            for (int j = 0; j < nbRows; j++) { t.Add(new List<int>()); }
            for (int i = 0; i < table.Count; i++)
            {
                for (int j = 0; j < table[i].Count; j++)
                {
                    t[j].Add(table[i][j]);
                }
            }
            return t;
        }

    }
}
