大家好Linq专家,
我想知道如何解决以下问题:
有一个字符串数组:
string[] words={"a#p#e","#pp#e","a##le"};
如何通过Linq获得“apple”这个词?
非常感谢!
答案 0 :(得分:2)
words.SelectMany(ar=>ar.Select((c,i)=>new{Index=i, Letter = c}).Where(o=>char.IsLetter(o.Letter))).OrderBy(o=>o.Index).GroupBy(o=>o).Select(g=>g.Key);
最有可能的是,这可以简化,但是,它可以工作(在LinqPad中快速组合在一起)。
这假设您只使用字母(可以修改为使用char.IsLetterOrDigit
),或使用Where
中的其他过滤。
此外,特别是对于@MarkPeters,一种查询语法,正确命名为version:
from partialWord in words
from characterWithPosition in partialWord.Select((character, position) => new{character,position})
where char.IsLetter(characterWithPosition.character)
orderby characterWithPosition.position
group characterWithPosition by characterWithPosition into allCharactersWithPositions
let singleCharacterWithPosition = allCharactersWithPositions.Key
select singleCharacterWithPosition.character
答案 1 :(得分:2)
这应该有效:
string[] words = { "a#p#e", "#pp#e", "a##le" };
var apple = words
.Aggregate(
(str1, str2) => { return String.Concat(str1.Zip(str2,
(c1, c2) => c1 == '#' ? c2 : c1).ToArray());
});
它的工作原理是检查第一个字符串中是否有任何不需要的字符,并用第二个字符串中的相应字符替换它们。然后将合并的字符串传递给下一个迭代,其中合并下两个字符串。最后返回结果。
答案 2 :(得分:0)
@ mrbraitwistle的答案是正确的解决方案;在IEnumerable<char>.Zip
方法
IEnumerable<string>.Aggregate
方法
以下答案为@ Gerino的答案部分提供了明确的类型定义,它使用了相当多的anonyomous类型和委托;另外,这个答案使用Linq.Expressions
和IQueryable<T>
;
虽然有一个问题,但它位于GetHashCode
下面的IndexLetterPair
类型中。
我们将创建一个具体类型,而不是声明匿名类型new { Index = i, Letter = c }
;但是,GroupBy
将无法正常运行,除非我们覆盖GetHashCode
object
方法(我们的类型继承)。我们还将实现IEquatable接口(其中T是另一个IndexLetterPair),此接口将由IQueryable<T>.GroupBy
方法使用。
此外,也可以覆盖object.Equal
方法 - 尽管由于GetHashCode
被覆盖,可能不必这样做。
public class IndexLetterPair IEquatable<IndexLetterPair>
{
public int Index { get; set; }
public char Letter { get; set; }
public override int GetHashCode()
{
return new { Index = this.Index, Letter = this.Letter }.GetHashCode();
}
// (new IndexLetterPair() as object).Equals(new IndexLetterPair());
public override bool Equals(object obj)
{
return (this.GetHashCode() == obj.GetHashCode());
}
// new IndexLetterPair().Equals(new IndexLetterPair());
public bool Equals(IndexLetterPair other)
{
return (this.GetHashCode() == other.GetHashCode());
}
}
为了方便,我们将声明一个IQueryable<string>
的扩展类和方法,它执行/声明我们定义的表达式的序列。
using Linq.Expressions;
public static class MyQueryableStringExtensions
{
readonly static Func<char, int, IndexLetterPair> SelectCharIndexPairingClause = (c, i) => new IndexLetterPair() { Index = i, Letter = c };
readonly static Func<IndexLetterPair, bool> WhereIsLetter = (dyn) => char.IsLetter(dyn.Letter);
readonly static Expression<Func<string, IEnumerable<IndexLetterPair>>> ManyClause = (arr) => arr.Select(SelectCharIndexPairingClause).Where(WhereIsLetter);
readonly static Expression<Func<IndexLetterPair, int>> OrderByIndexClause = (pairing) => pairing.Index;
readonly static Expression<Func<IndexLetterPair, IndexLetterPair>> GroupByClause = (pairing) => pairing;
// if IEquatable<IndexLetterPair> is implemented ? uses IEquatable<IndexLetterPair>.Equals : (IndexLetterPair() as object).Equals
readonly static Expression<Func<IGrouping<IndexLetterPair, IndexLetterPair>, IndexLetterPair>> GroupSelectKeyClause = (pairing) => pairing.Key;
public static IQueryable<char> SelectManyGroupedLetterChars(this IQueryable<string> words)
{
return words.SelectMany(ManyClause)
.OrderBy(OrderByIndexClause)
.GroupBy(GroupByClause)
.Select(GroupSelectKeyClause)
.Select((pair) => pair.Letter);
}
}
string[] words = new string[] { "a#p#e", "#pp#e", "a##le" };
IQueryable<string> queryableWords = words.AsQueryable();
IQueryable<char> queryGroupedLetterChars = queryableWords.SelectManyGroupedLetterChars();
// string(char[]);
string word = new string(queryGroupedLetterChars.ToArray());