2

我有以下方法可以打印出给定数组的所有连续子集。我希望能够将交织在 for 循环中的丑陋 print 语句分离出来并放入一个新函数中。这是可行的吗?

    // Example:  
    // Input: char[] input = new char[] { 'a', 'b', 'c' };
    // Output: 
    //        (a) (a b) (a b c)
    //        (b) (b c)
    //        (c)  

    static void  PrintContSubArrays(char[] arr)
    {
        int len = arr.Length;
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();

        for (int i = 0; i < len; i++)
        {
            for (int j = 1; j <= len; j++)
            {
                sb2.AppendFormat("(");

                for (int k = i; k < j; k++)
                {
                    sb2.AppendFormat("{0} ", arr[k]);
                }

                sb2.Remove(sb2.Length - 1, 1);
                sb2.Append(") ");

                if (sb2.Length > 3) sb1.Append(sb2);
                sb2.Clear();
            }
            sb1.Append(System.Environment.NewLine);
        }

        Console.WriteLine(sb1.ToString());
        Console.ReadLine();
    }
4

4 回答 4

2

Implemented this based on suggestion by @usr

Instead of doing the string processing inline extract the subarrays as char[] and return them using yield return. That way the caller receives a stream of subarrays. He can process, format and print them as he wants.

This is what I have. But this does not translate to your exact output format. Some formatting is lost due to loss of context. If you are willing to pass in the original array length into the print method, you could get exactly what you need by tweaking the for-loop in print method.

    // Input: int[] input = new int[] { 1, 2, 3};
    // Call: Console.WriteLine(PrintContSubArrays(GetContSubArrays(input)));
    // Output: 
    //       (1)
    //       (1 2)
    //       (1 2 3)
    //       (2)
    //       (2 3)
    //       (3)

    // Generate subsets
    static IEnumerable<int[]> GetContSubArrays(int[] arr)
    {
        int len = arr.Length;

        for (int i = 0; i < len; i++)
        {
            for (int j = 1; j <= len; j++)
            {
                int[] placeholder = new int[j - i < 0 ? 0 : j - i];
                bool isPlaceholderEmpty = true;

                for (int k = i; k < j; k++)
                {
                    placeholder[k - i] = arr[k];
                    isPlaceholderEmpty = false;
                }
                if (!isPlaceholderEmpty) yield return placeholder;
            }
        }
    }

    // Print
    static string PrintContSubArrays(IEnumerable<int[]> input)
    {
        StringBuilder sb1 = new StringBuilder();

        foreach (int[] intarr in input)
        {
            if (intarr != null)
            {
                sb1.Append("(");
                foreach (int intsingle in intarr)
                {
                    sb1.AppendFormat("{0} ", intsingle);
                }
                sb1.Remove(sb1.Length - 1, 1);
                sb1.Append(")");
            }
            sb1.AppendFormat(Environment.NewLine);
        }

        return sb1.ToString();
    }
于 2015-02-04T23:25:05.447 回答
1

而不是进行字符串处理内联提取子数组char[]并使用yield return. 这样调用者就会收到一个子数组流。他可以随心所欲地处理、格式化和打印它们。

于 2015-02-04T20:15:12.197 回答
1

这样做怎么样?

static void PrintContSubArrays(char[] arr)
{
    Console.WriteLine(String.Join(Environment.NewLine,
            from n1 in Enumerable.Range(0, arr.Length)
            select String.Join(" ",
                from n2 in Enumerable.Range(1, arr.Length - n1)
                select String.Format("({0})", String.Join(" ", arr.Skip(n1).Take(n2))))));
    Console.ReadLine();
}

这样你也可以摆脱所有丑陋的循环。

于 2015-02-05T01:48:15.433 回答
1

这是简化事情的一种方法:

static void PrintContiguousSubArrays( char[] input )
{
  if ( input == null ) throw new ArgumentNullException("input") ;
  if ( input.Length == 0 ) return ;

  for ( int offset = 0 ; offset < input.Length ; ++offset )
  {
    string separator = "" ;

    for ( int length = 1 ; offset+length <= input.Length ; ++length )
    {
      Console.Write( "{0}[{1}]" ,
        separator ,
        string.Join("," , input.Skip(offset).Take(length).Select( c => new string(c,1) ) )
        );
      separator = " ";
    }
    Console.WriteLine();

  }

  return ;
}

这是另一种方式:

static IEnumerable<IEnumerable<char>> ContiguousSubArraysOf( char[] input )
{
  if ( input == null ) throw new ArgumentNullException("input") ;

  for ( int offset = 0 ; offset < input.Length ; ++offset )
  {
    for ( int length = 1 ; offset+length <= input.Length ; ++length )
    {
      yield return input.Skip(offset).Take(length) ;
    }
  }

}

这会让你说这样的话:

char[] input = "abc".ToCharArray();

foreach( var item in ContiguousSubArraysOf(input) )
{
  Console.WriteLine( "[{0}]" ,
    string.Join( "," , item.Select( c => new string(c,1) ) )
  ) ;
}
于 2015-02-05T00:35:32.233 回答