我们有一个带有几个点分离值的输入字符串,这些单元中的每个单元都被空间隔开。如果输入就像:
字符串输入=" 1.2 3.4 5.6 7.8 9",我们需要将其分解为:
字符串beforedots =" 1,3,5,7,9"//点之前所有ints。
字符串frestdots =" 2,4,6,8"//点之后的所有ints。
我们尝试了以下方法:
string inputSplit=input.Split(' ');
string beforeDots=string.Empty;
string afterDots=string.Empty;
foreach (string input in inputSplit)
{
if (input.IndexOf(".") > 0)
afterDots += "," + s.Split('.')[1];
else
beforeDots += "," + s;
}
if(afterDots.Length > 0)
afterDots = afterDots.Substring(1, afterDots.Length - 1);
if(beforeDots.Length > 0)
beforeDots = beforeDots.Substring(1, beforeDots.Length - 1);
有什么更好的方法可以通过linq或更轻松的逻辑解决此问题?
您可以稍微清理逻辑:
string input = "1.2 3.4 5.6 7.8 9";
List<string> beforeDot = new List<string>();
List<string> afterDot = new List<string>();
foreach(string s in input.Split())
{
var split = s.Split('.');
beforeDot.Add(split[0]);
if(split.Length == 2)
{
afterDot.Add(split[1]);
}
}
string beforeDots = string.Join(", ", beforeDot);
string afterDots = string.Join(", ", afterDot);
这为您提供了单独保留的数字(beforedot,fasterdot)的额外好处,如果您需要将其用于其他逻辑。
确实没有任何需要在此处使用Linq。
小提琴
您可以使用极其简单且可调的代码对任何T
进行概括,而无需使用LINQ:
public static (IEnumerable<T> Prefixes, IEnumerable<T> suffixes)
Separate<T>(this IEnumerable<T> source, T splitOn, T resetOn)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
var isSuffix = false;
var prefixes = new List<T>();
var suffixes = new List<T>();
foreach (var c in source)
{
if (c.Equals(splitOn))
{
isSuffix = true;
}
else if (c.Equals(resetOn))
{
isSuffix = false;
}
else
{
if (isSuffix)
{
suffixes.Add(c);
}
else
{
prefixes.Add(c);
}
}
}
return (prefixes, suffixes);
}
用法相当简单:
var res = "1.2 3.4 5.6 7.8 9".Separate('.', ' ');
输出是字符串(可以在事实之后解析):
class Program
{
static void Main(string[] args)
{
var input = "1.2 3.4 5.6 7.8 9";
var pairs = input.Split(' ').Select(
s =>
{
var split = s.Split('.');
return new KeyValuePair<string,string>(split[0],split.Length > 1 ? split[1] : null);
});
Console.WriteLine(String.Join(",", pairs.Select(p => p.Key)));
Console.WriteLine(String.Join(",", pairs.Where(p=>p.Value != null).Select(p => p.Value)));
Console.ReadKey();
}
}
你,伙计们,正在过度复杂化。总而言之,这些只是十进制数字。所以我要这样做:
static void Main(string[] args)
{
var input = "1.2 3.4 5.6 7.8 9";
var numbers = input.Split().Select(s => decimal.Parse(s));
var beforeDots = numbers.Select(n => (int)Math.Truncate(n));
var afterDots = numbers.Select(n => (int)((n - Math.Truncate(n)) * 10));
Console.WriteLine(string.Join(",", beforeDots));
Console.WriteLine(string.Join(",", afterDots));
Console.ReadLine();
}
// Output:
// 1,3,5,7,9
// 2,4,6,8,0
我建议分开字符串,然后使用linq。
编辑:我错过了以前数字之间的空间,以下更新的方法将与所考虑的空间一起使用。
string input = "1.2 3.4 5.6 7.8 9";
//split, assign index, flatten, group by index.
var inputGroups = input.Split(' ').Select(x => x.Split('.')).Select(x=>x.Select((number, i)=>new { Number = number, Index = i })).SelectMany(x=>x).GroupBy(x=>x.Index);
//group with index 0 was before the dot
var beforeDot= inputGroups.Where(grp=>grp.Key == 0) .FirstOrDefault().Select(x=>x.Number);
//group with key 1 was after the dot
var afterDot= inputGroups.Where(x=>x.Key == 1).FirstOrDefault().Select(x => x.Number);
//then use string.Join(",", str);
var commaSeparatedBefore = string.Join(",",beforeDot);
var commaSeparatedAfter = string.Join(",", afterDot);
您可以做到这一点:
var tmp = input.Split(' ').Select(x => x.Split('.'));
var beforeDots = string.Join(",", tmp.Select(x => x.First()));
var afterDots = string.Join(",", tmp.Select(x => x.ElementAtOrDefault(1)).Where(x => x != null));