我正在解决我在C#中解决的问题,但现在我将我的代码移植到F#。我有一个字节数组,我需要在这个数组中搜索两个值(x,y)。当我找到x
时,需要检查:如果y
在下一个索引上,我们就匹配了。如果y
不在下一个索引上,则搜索将继续。我该如何解决这个问题?我尝试使用Array.findIndex
,但没有成功,因为当y
不在下一个索引时,我不知道如何继续搜索。
编辑:
public void GetValue(byte[] data)
{
byte[] temp = new byte[4];
for (int i = 0; i < data.Length; i++)
{
if (data[i] == Adress[0] && data[i + 1] == Adress[1])
{
for (int j = 0; j < temp.Length; j++)
{
temp[j] = data[j + i + 2];
}
Value = BitConverter.ToInt32(temp, 0) * 0.01;
break;
}
}
答案 0 :(得分:9)
您可以轻松地将其变为功能:
let bytes = [| 104uy; 101uy; 108uy; 108uy; 111uy |]
bytes
|> Array.pairwise
|> Array.findIndex (fun x -> fst x = snd x)
//2
答案 1 :(得分:3)
你已经接受了你的答案,但我对你的评论感到震惊“我很惊讶在功能编程中可以提供干净的解决方案”。
您也可以在功能上编写C#代码:
var index = Enumerable.Range(0, Int32.MaxValue)
.Zip(bytes.Zip(bytes.Skip(1)))
.Where(triplet => triplet.Item2.Item1 == triplet.Item2.Item2)
.Select(triplet => triplet.Item1)
.DefaultIfEmpty(-1)
.First();
如果你更进一步,你可以为IEnumerable<T>
创建一些扩展方法:
public static class EnumerableExt
{
public static IEnumerable<Tuple<A, A>> Pairwise<A>(this IEnumerable<A> self) =>
self.Zip(self.Skip(1));
public static int IndexOf<A>(this IEnumerable<A> self, Func<A, bool> f) =>
Enumerable.Range(0, Int32.MaxValue)
.Zip(self)
.Where(x => f(x.Item2))
.Select(x => x.Item1)
.DefaultIfEmpty(-1)
.FirstOrDefault();
}
然后,它将为您提供与您接受的F#版本几乎完全相同的代码:
var index = bytes.Pairwise()
.IndexOf(x => x.Item1 == x.Item2);
C#本身就是一种非常强大的功能语言。如果你有混合C#和F#的项目,并且你希望你的C#看起来和你的F一样好,那么你可能想尝试my functional base class library for C#。
答案 2 :(得分:1)
您的C#代码可以按如下方式转换为F#(更好的索引检查,因此您不会遍历数据数组的边界):
let getValue (a : _ []) (d : _ []) =
let rec aux i =
if i > data.Length - 6 then nan
elif d.[i] = a.[0] && d.[i + 1] = a.[1] then
0.01 * float (System.BitConverter.ToInt32 (d, i + 2))
else aux (i + 1)
aux 0
let value = getValue address data
但是,与手动递归循环相比,重用库函数可以使代码更容易读取,我们也可以按照建议使用Array.pairwise
:
let getValue2 (a : byte []) d =
d |> Array.pairwise
|> Array.tryFindIndex (fun (x, y) -> x = a.[0] && y = a.[1])
|> Option.map (fun i ->
0.01 * float (System.BitConverter.ToInt32 (d, i + 2)))
|> function None -> nan | Some v -> v