C# 如何一次选择两个项目?
我当时正在使用C# 如何一次选择两个项目?,c#,regex,linq,C#,Regex,Linq,我当时正在使用Regex.Split编写一个PascalCasperser,我希望一次从一个集合中选择两个项目 此示例代码演示 void Main() { string pascalCasedString = "JustLikeYouAndMe"; var words = WordsFromPascalCasedString(pascalCasedString); words.Dump(); } IEnumerable<string> WordsFromPa
Regex.Split
编写一个PascalCasperser,我希望一次从一个集合中选择两个项目
此示例代码演示
void Main()
{
string pascalCasedString = "JustLikeYouAndMe";
var words = WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable<string> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
return rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
// how to select 2 elements at a time?
;
}
void Main()
{
string pascalCasedString=“JustLikeYouAndMe”;
var words=WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable words frompascalcasedstring(string pascalCasedString)
{
var rx=新正则表达式(([A-Z]);
返回rx.Split(PASCALCSEDSTRING)
.Where(c=>!string.IsNullOrEmpty(c))
//如何一次选择2个元素?
;
}
上述代码的结果是:
IEnumerable<String> (10 items)
J
ust
L
ike
Y
ou
A
nd
M
e
IEnumerable(10项)
J
乌斯特
L
艾克
Y
欧点
A.
钕
M
E
集合的每两个元素生成一个结果,我希望函数WordsFromPascalCasedString
生成该结果
我的问题是:一般来说,您如何处理一次退回两件物品的要求。我很好奇是否有任何有趣的非暴力方法。正则表达式应该是([A-Z][A-Z]*)
。如果还想包含数字,请调整最后一部分。如果希望在大写分隔符后至少有一个小写元素,请使用+
而不是*
Edit对于实际问题,您需要在for
循环中具体化和迭代,以获得更好的性能(通过列表一次)。在您的特定问题中,您可以使用Regex.Matches
var result = Regex.Matches("([A-Z][a-z]*)([A-Z][a-z]*)?", "AbCdEfGhIj")
.OfType<Match>()
.Where(m => m.Success)
.Select(m => Tuple.Create(m.Groups[1].Value, m.Groups[2].Value));
var result=Regex.Matches(([A-Z][A-Z]*)([A-Z][A-Z]*)?,“AbCdEfGhIj”)
第()类
.其中(m=>m.Success)
.Select(m=>Tuple.Create(m.Groups[1].Value,m.Groups[2].Value));
就我个人而言,在这种特殊情况下,我会同意西蒙·贝朗格的答案。但一般来说,要从IEnumerable
中选择连续对,您可以使用以下方法:
IEnumerable<Tuple<string, string>> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
var array = rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
.ToArray();
var items = Enumerable.Range(0, array.Length / 2)
.Select(i => Tuple.Create(array[i * 2], array[i * 2 + 1]);
}
类似的方法存在于。中,最简单的方法是编写只返回对的函数 比如:
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> items)
{
T first = default(T);
bool hasFirst = false;
foreach(T item in items)
{
if (hasFirst)
yield return Tuple.Create(first, item);
else
first = item;
hasFirst = !hasFirst;
}
}
奇偶元素(索引%2==/!=0
)的Zip
是两行方法。请注意,迭代源集合两次
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> collection)
{
return collection
.Where((item, index)=>index %2 == 0)
.Zip(collection.Where((item, index)=>index %2 != 0),
(first,second)=> Tuple.Create(first,second));
}
IEnumerable对(IEnumerable集合)
{
回收
。其中((项目,索引)=>索引%2==0)
.Zip(集合.其中((项,索引)=>索引%2!=0),
(第一,第二)=>Tuple.Create(第一,第二));
}
这只是为了与大家分享,我在受到其他答案的启发后,提出了一个解决方案。它并不比其他的好
void Main()
{
string pascalCasedString = "JustLikeYouAndMe";
var words = WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable<string> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
return rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
.InPieces(2)
.Select(c => c.ElementAt(0) + c.ElementAt(1));
}
static class Ext
{
public static IEnumerable<IEnumerable<T>> InPieces<T>(this IEnumerable<T> seq, int len)
{
if(!seq.Any())
yield break;
yield return seq.Take(len);
foreach (var element in InPieces(seq.Skip(len), len))
yield return element;
}
}
void Main()
{
string pascalCasedString=“JustLikeYouAndMe”;
var words=WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable words frompascalcasedstring(string pascalCasedString)
{
var rx=新正则表达式(([A-Z]);
返回rx.Split(PASCALCSEDSTRING)
.Where(c=>!string.IsNullOrEmpty(c))
.输入文件(2)
.选择(c=>c.ElementAt(0)+c.ElementAt(1));
}
静态类扩展
{
公共静态IEnumerable InPieces(此IEnumerable seq,int len)
{
如果(!seq.Any())
屈服断裂;
收益率-收益序列(len);
foreach(输入中的var元素(序列跳过(len),len))
收益-收益要素;
}
}
+1用于解决我的实际问题(谢谢)。。。如果我问的问题得到了答案,我还是会感兴趣的…还有一个问题是什么?是的,我并没有真正尝试去弄清楚解析器,我真的很感兴趣看到其他人想使用linq风格的select,一次处理两个项目。。。但我再次感谢您的帮助这是一个纯粹的娱乐答案-p.s.w.g(+1)已经介绍了创建配对的更好版本。+1我见过许多“批处理”技术,但这是我见过的第一个递归技术。它可能不是最有效率的,但绝对是有创意的。
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> collection)
{
return collection
.Aggregate(
Tuple.Create(false, default(T), Enumerable.Empty<Tuple<T,T>>()),
(accumulate, item)=> !accumulate.Item1 ?
Tuple.Create(true, item, accumulate.Item3) :
Tuple.Create(false, default(T),
accumulate.Item3.Concat(
Enumerable.Repeat(Tuple.Create(accumulate.Item2, item), 1))),
accumulate => accumulate.Item3);
}
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> collection)
{
return collection
.Where((item, index)=>index %2 == 0)
.Zip(collection.Where((item, index)=>index %2 != 0),
(first,second)=> Tuple.Create(first,second));
}
void Main()
{
string pascalCasedString = "JustLikeYouAndMe";
var words = WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable<string> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
return rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
.InPieces(2)
.Select(c => c.ElementAt(0) + c.ElementAt(1));
}
static class Ext
{
public static IEnumerable<IEnumerable<T>> InPieces<T>(this IEnumerable<T> seq, int len)
{
if(!seq.Any())
yield break;
yield return seq.Take(len);
foreach (var element in InPieces(seq.Skip(len), len))
yield return element;
}
}