我有以下方法打印出给定数组的所有连续子集。我希望能够将在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();
}
答案 0 :(得分:2)
根据@usr
的建议实现此目的而不是进行字符串处理内联提取子数组
char[]
并使用yield return
返回它们。那样的来电者 接收一组子数组。他可以处理,格式化和打印它们 他想要的。
这就是我所拥有的。但这并不能转化为您的确切输出格式。由于丢失了上下文,某些格式会丢失。如果您愿意将原始数组长度传递给print方法,则可以通过调整print方法中的for循环来获得所需的内容。
// 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();
}
答案 1 :(得分:1)
不使用内联字符串处理,而是将子数组提取为char[]
,并使用yield return
返回它们。这样调用者就会收到一组子数组。他可以随意处理,格式化和打印它们。
答案 2 :(得分: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) ) )
) ;
}
答案 3 :(得分: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();
}
这样你就可以摆脱所有丑陋的循环。