【问题标题】:Find string permutation including the single character using C# or F#使用 C# 或 F# 查找字符串排列,包括单个字符
【发布时间】:2011-08-30 15:21:10
【问题描述】:

我想生成一个包含可变字符列表的字符串的所有可能排列的列表。 例如,如果我有字符串“ABC”,我想要一个包含所有可能变体的列表,例如:A、B、C、AB、BC。

谢谢。

【问题讨论】:

标签: c# .net f#


【解决方案1】:

很难确切地说出您想要什么,但根据您的示例输出,这里是如何做我认为您在 F# 中所追求的。

let combinations (s:string) =
  let rec loop acc i =
    seq {
      for i in i .. (s.Length - 1) do
        let acc = acc + s.[i..i]
        yield acc
        yield! loop acc (i + 1)
    }
  loop "" 0

combinations "ABC" |> Seq.toList //["A"; "AB"; "ABC"; "AC"; "B"; "BC"; "C"]

【讨论】:

    【解决方案2】:

    这是一个 LINQ 版本:

    Func<string, IEnumerable<string>> perm = t =>
    {
        Func<string, string, IEnumerable<string>> perm2 = null;
        perm2 =
            (t0, t1s) =>
                from n in Enumerable.Range(0, t1s.Length)
                let c = t1s.Substring(n, 1)
                let x = t1s.Remove(n, 1)
                let h = t0 + c
                from r in (new [] { h, }).Concat(perm2(h, x))
                select r;
        return perm2("", t);
    };
    

    像这样使用它:

    var ps = perm("abc");
    

    它会执行惰性计算。

    var ps = perm("abcdefghijklmnopqrstuvwxyz").Take(2);
    // Only computes two values when executed
    

    【讨论】:

      【解决方案3】:

      这里将返回给定一串字符的所有排列(不是不同的)。它既不快速也不高效,但它确实有效......

        public List<string> permute(string value, string prefix = "")
          {
              List<string> result = new List<string>();
              for (int x=0;x<value.Length;x++)
              {
                  result.Add(prefix + value[x]);
                  result.AddRange(permute( value.Remove(x, 1), prefix + value[x]));
              }
              return result;
          }
      

      使用方法:

             List<string> output = permute("abc");
      

      【讨论】:

        【解决方案4】:

        在 F# Snippets 上查看此 snippet

        【讨论】:

          【解决方案5】:

          如果您正在按索引查找排列(而不是必须遍历所有排列),您可以使用称为 factoradics (Source) 的编号系统来查找它们。这是来自原文章的代码,具有更强的 C# 风格(原代码非常'C++ish')和泛型。

          /// <summary>
          /// Permutes the specified atoms; in lexicographical order.
          /// </summary>
          /// <typeparam name="T">The type of elements.</typeparam>
          /// <param name="atoms">The atoms.</param>
          /// <param name="index">The index of the permutation to find.</param>
          /// <returns>The permutation.</returns>
          public static IList<T> Permute<T>(this IList<T> atoms, int index)
          {
              var result = new T[atoms.Count];
              Permute(atoms, result, index);
              return result;
          }
          
          /// <summary>
          /// Permutes the specified atoms; in lexicographical order.
          /// </summary>
          /// <typeparam name="T">The type of elements.</typeparam>
          /// <param name="atoms">The atoms.</param>
          /// <param name="target">The array to place the permutation in.</param>
          /// <param name="index">The index of the permutation to find.</param>
          public static void Permute<T>(this IList<T> atoms, IList<T> target, int index)
          {
              if (atoms == null)
                  throw new ArgumentNullException("atoms");
              if (target == null)
                  throw new ArgumentNullException("target");
              if (target.Count < atoms.Count)
                  throw new ArgumentOutOfRangeException("target");
              if (index < 0)
                  throw new ArgumentOutOfRangeException("index");
          
              var order = atoms.Count;
          
              // Step #1 - Find factoradic of k
              var perm = new int[order];
              for (var j = 1; j <= order; j++)
              {
                  perm[order - j] = index % j;
                  index /= j;
              }
          
              // Step #2 - Convert factoradic[] to numeric permuatation in perm[]
              var temp = new int[order];
              for (var i = 0; i < order; i++)
              {
                  temp[i] = perm[i] + 1;
                  perm[i] = 0;
              }
          
              perm[order - 1] = 1;  // right-most value is set to 1.
              for (var i = order - 2; i >= 0; i--)
              {
                  perm[i] = temp[i];
                  for (var j = i + 1; j < order; j++)
                  {
                      if (perm[j] >= perm[i])
                          perm[j]++;
                  }
              }
          
              // Step #3 - map numeric permutation to string permutation
              for (var i = 0; i < order; ++i)
              {
                  target[i] = atoms[perm[i] - 1];
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-26
            • 2019-01-28
            • 2019-11-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多