Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有限长度的c#列表置换_C#_List_Permutation - Fatal编程技术网

有限长度的c#列表置换

有限长度的c#列表置换,c#,list,permutation,C#,List,Permutation,我有一个报价列表,我想从中创建链长度有限的“链”(例如排列) 我已经用Kw组合学创建了排列。 但是,默认行为会在列表计数的长度中创建排列。我不知道如何将链条长度限制为“n” 以下是我当前的代码: private static List<List<Offers>> GetPerms(List<Offers> list, int chainLength) { List<List<Offers>> respon

我有一个报价列表,我想从中创建链长度有限的“链”(例如排列)

我已经用Kw组合学创建了排列。 但是,默认行为会在列表计数的长度中创建排列。我不知道如何将链条长度限制为“n”

以下是我当前的代码:

    private static List<List<Offers>> GetPerms(List<Offers> list, int chainLength)
    {
        List<List<Offers>> response = new List<List<Offers>>();
        foreach (var row in new Permutation(list.Count).GetRows())
        {
            List<Offers> innerList = new List<Offers>();
            foreach (var mix in Permutation.Permute(row, list))
            {
                innerList.Add(mix);

            }
            response.Add(innerList);
            innerList = new List<Offers>();
        }
        return response;
    }
private static List GetPerms(List List,int chainLength)
{
列表响应=新列表();
foreach(新排列中的var行(list.Count).GetRows())
{
List innerList=新列表();
foreach(置换中的var混合。置换(行,列表))
{
innerList.Add(mix);
}
Add(innerList);
innerList=新列表();
}
返回响应;
}
执行人:

List<List<AdServer.Offers>> lst = GetPerms(offers, 2);
List lst=GetPerms(提供,2);

如果有人能提供更好的解决方案,我不会拘泥于组合数学。

你不是在寻找置换,而是在寻找变异。这里有一个可能的算法。对于可能返回很多元素的函数,我更喜欢迭代器方法。这样,调用者就可以决定他是否真的需要所有元素:

IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
    var startIndices = new int[length];
    var variationElements = new HashSet<T>(); //for duplicate detection

    while (startIndices[0] < offers.Count)
    {                
        var variation = new List<T>(length);
        var valid = true;
        for (int i = 0; i < length; ++i)
        {
            var element = offers[startIndices[i]];
            if (variationElements.Contains(element))
            {
                valid = false;
                break;
            }
            variation.Add(element);
            variationElements.Add(element);
        }
        if (valid)
            yield return variation;

        //Count up the indices
        startIndices[length - 1]++;
        for (int i = length - 1; i > 0; --i)
        {
            if (startIndices[i] >= offers.Count)
            {
                startIndices[i] = 0;
                startIndices[i - 1]++;
            }
            else
                break;
        }
        variationElements.Clear();
    }
}

如果我没弄错,这就是你需要的

这将根据指定的链限制创建置换

    public static List<List<T>> GetPerms<T>(List<T> list, int chainLimit)
    {
        if (list.Count() == 1)
            return new List<List<T>> { list };
        return list
            .Select((outer, outerIndex) =>
                        GetPerms(list.Where((inner, innerIndex) => innerIndex != outerIndex).ToList(), chainLimit)
            .Select(perms => (new List<T> { outer }).Union(perms).Take(chainLimit)))
            .SelectMany<IEnumerable<IEnumerable<T>>, List<T>>(sub => sub.Select<IEnumerable<T>, List<T>>(s => s.ToList()))
            .Distinct(new PermComparer<T>()).ToList();
    }

    class PermComparer<T> : IEqualityComparer<List<T>>
    {
        public bool Equals(List<T> x, List<T> y)
        {
            return x.SequenceEqual(y);
        }

        public int GetHashCode(List<T> obj)
        {
            return (int)obj.Average(o => o.GetHashCode());
        }
    }
publicstaticlist-GetPerms(List-List,int-chainLimit)
{
if(list.Count()==1)
返回新列表{List};
返回列表
.选择((外部,外部索引)=>
GetPerms(list.Where((内部,内部索引)=>innerIndex!=outerIndex.ToList(),chainLimit)
.Select(perms=>(新列表{outer}).Union(perms.Take(chainLimit)))
.SelectMany(sub=>sub.Select(s=>s.ToList())
.Distinct(新的PermComparer()).ToList();
}
类PermComparer:IEqualityComparer
{
公共布尔等于(列表x、列表y)
{
返回x.x(y);
}
public int GetHashCode(列表对象)
{
return(int)obj.Average(o=>o.GetHashCode());
}
}
你会这样称呼它

 List<List<AdServer.Offers>> lst = GetPerms<AdServer.Offers>(offers, 2);
List lst=GetPerms(提供,2);
我使这个函数非常通用,因此您也可以将其用于其他用途

乙二醇

List List=新列表(新[]{“苹果”、“香蕉”、“橘子”、“樱桃”});
List perms=GetPerms(List,2);
结果


这里是另一个实现,我认为它应该比公认的答案更快(而且代码肯定更少)

使用编译器优化

GetVariations                           9667 ms
GetVariationsWithoutDuplicates          8 ms
OtherAnswerGetVariations                19739 ms
OtherAnswerGetVariationsWithDuplicates  228802 ms

您能不能用
chainLength
替换
列表。Count
呢?很抱歉回复太晚,但这正是我想要的,谢谢!
    List<string> list = new List<string>(new[] { "apple", "banana", "orange", "cherry" });
    List<List<string>> perms = GetPerms<string>(list, 2);
public static IEnumerable<IEnumerable<T>> GetVariationsWithoutDuplicates<T>(IList<T> items, int length)
{
  if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
  return from item in items.Distinct()
         from permutation in GetVariationsWithoutDuplicates(items.Where(i => !EqualityComparer<T>.Default.Equals(i, item)).ToList(), length - 1)
         select Prepend(item, permutation);
}

public static IEnumerable<IEnumerable<T>> GetVariations<T>(IList<T> items, int length)
{
  if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
  return from item in items
         from permutation in GetVariations(Remove(item, items).ToList(), length - 1)
         select Prepend(item, permutation);
}

public static IEnumerable<T> Prepend<T>(T first, IEnumerable<T> rest)
{
  yield return first;
  foreach (var item in rest) yield return item;
}

public static IEnumerable<T> Remove<T>(T item, IEnumerable<T> from)
{
  var isRemoved = false;
  foreach (var i in from)
  {
    if (!EqualityComparer<T>.Default.Equals(item, i) || isRemoved) yield return i;
    else isRemoved = true;
  }
}
public static void Test(Func<IList<int>, int, IEnumerable<IEnumerable<int>>> getVariations)
{
  var max = 11;
  var timer = System.Diagnostics.Stopwatch.StartNew();
  for (int i = 1; i < max; ++i)
    for (int j = 1; j < i; ++j)
      getVariations(MakeList(i), j).Count();
  timer.Stop();
  Console.WriteLine("{0,40}{1} ms", getVariations.Method.Name, timer.ElapsedMilliseconds);
}

// Make a list that repeats to guarantee we have duplicates
public static IList<int> MakeList(int size)
{
  return Enumerable.Range(0, size/2).Concat(Enumerable.Range(0, size - size/2)).ToList();
}
GetVariations                           11894 ms
GetVariationsWithoutDuplicates          9 ms
OtherAnswerGetVariations                22485 ms
OtherAnswerGetVariationsWithDuplicates  243415 ms
GetVariations                           9667 ms
GetVariationsWithoutDuplicates          8 ms
OtherAnswerGetVariations                19739 ms
OtherAnswerGetVariationsWithDuplicates  228802 ms