IEnumerable Group連續/相鄰元素

  • 82
  • 0

記錄下這次找到的參考資料

一個由小寫英文字母組成的字串(如:aabbbbbbcca),該如何找出該字串中所有字元都相同的子字串(如:aa、bbbbbb)?

思路之一就是循序比對字元,在stackoverflow上找到有人提出類似問題並且得到了回答

https://stackoverflow.com/questions/20469416/linq-to-find-series-of-consecutive-numbers/20469961

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> src, Func<T,T,bool> condition)
{
	if (!src.Any())
		yield break;
	
	T prev = src.First();
	List<T> list = new List<T>() { prev };

	foreach(T item in src.Skip(1))
	{
		if (!condition(prev,item))
		{
			yield return list;
			list = new List<T>();
		}
		list.Add(item);
		prev = item;
	}
	yield return list;
}

將此方法套用上確實能如預期運作

也有人提到MoreLinq有提供類似的方法GroupAdjacent可以使用

https://stackoverflow.com/questions/14879197/linq-query-data-aggregation-group-adjacent

https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/GroupAdjacent.cs


另一思路就是透過正規表示式的backreference匹配

前面的([\w])匹配一個英文字並記為一個群組,之後的\1*代表要匹配與群組1相同的內容任意次數

// 以群組編號指定,語法 \群組編號
Regex.Matches("aabbbbbbcca", @"([\w])\1*").Cast<Match>().Select(x => x.Value);

// 以群組名稱指定,語法 \k<群組名稱>
Regex.Matches("aabbbbbbcca", @"(?<groupName>[\w])\k<groupName>*").Cast<Match>().Select(x => x.Value);

https://docs.microsoft.com/zh-tw/dotnet/standard/base-types/backreference-constructs-in-regular-expressions

https://stackoverflow.com/questions/42001668/regular-expression-for-same-consecutive-numbers