我必须将以def pad(s):
for k, v in dictionary.items():
s = s.replace(k, v)
return s
>>> dictionary = { "(": " ( ", ")": " ) "}
>>> pad("if (x < 0) {")
'if ( x < 0 ) {'
开头的十六进制字符串或以0x
转换为十六进制的字符串转换为BitConverter
数组。为此,我使用此功能,效果很好:
byte
示例输入,来自某种网络设备(将其视为用wirehark记录的消息):
public static byte[] ConvertToByteArray(this string s)
{
if (s.StartsWith("0x"))
{
var ret = new byte[(s.Length - 2) / 2];
for (int i = 2; i < s.Length; i += 2)
{
ret[(i - 2) / 2] = Convert.ToByte(string.Concat(s[i], s[i + 1]), 16);
}
return ret;
}
else
return s.Split('-').Select(b => Convert.ToByte(b, 16)).ToArray();
}
现在,我想了解如何在LINQ中编写第一种可能性(以byte[] data1 = "0x020206000000022800A601585E40".ConvertToByteArray();
byte[] data2 = "02-02-06-00-00-00-02-28-00-A6-01-58-5E-40".ConvertToByteArray();
CollectionAssert.AreEqual(data1, data2);
开头),以摆脱1990年代的for循环。
是否可以同时选择两个字符,还是比我更优雅的方法?
答案 0 :(得分:1)
好吧,我想首先可以看看这个
使用@jdweng示例输入。
string input = "0x0123456789ABCDE".Replace("0x", string.Empty);
long intValue = long.Parse(s, System.Globalization.NumberStyles.HexNumber);
现在,如果您很长,可以轻松将其转换为byte []。
byte[] array = BitConverter.GetBytes(intValue);
我知道这不是LINQ解决您的问题的方法,但是它很干净而且很简单。
答案 1 :(得分:1)
阅读OP的评论后,我看到他希望能够使用任意长度的十六进制字符串。我很想使用迭代器函数返回您的十六进制对,以匹配拆分结果。然后,您可以通过相同的转换来提供任何可枚举的数据,例如:
public byte[] ConvertToByteArray(string s)
{
IEnumerable<string> query = Enumerable.Empty<string>();
if (s.StartsWith("0x"))
{
query = IterateHexPairs(s.Substring(2));
}
else
{
query = s.Split('-');
}
return query.Select(b => Convert.ToByte(b, 16)).ToArray();
IEnumerable<string> IterateHexPairs(string hexLiteral)
{
char? previousNibble = null;
foreach (var nibble in hexLiteral)
{
if (previousNibble != null)
{
yield return new string(new char[] { previousNibble.Value, nibble });
previousNibble = null;
}
else
{
previousNibble = nibble;
}
}
}
}
这避免了必须重复您的转换逻辑,因为它们都从IEnumerable获取。唯一的区别是IEnumerable的来源。更改适合您的枚举的代码。我认为Iterator函数将更易于维护,但您可以对Linq查询进行bodge以达到相同的结果,如下所示:
public byte[] ConvertToByteArray(string s)
{
IEnumerable<string> query = Enumerable.Empty<string>();
if (s.StartsWith("0x"))
{
// omit the 0x
query = s.Skip(2)
// get the char and index, so we can pair them up
.Select((c, i) => new { Char = c, Index = i })
// group them into pairs
.GroupBy(o => o.Index / 2)
// select them as new strings, so they can be converted
.Select(g => new string(g.Select(o => o.Char).ToArray()));
}
else
{
query = s.Split('-');
}
return query.Select(b => Convert.ToByte(b, 16)).ToArray();
}
答案 2 :(得分:1)
这是循环的linq等效项,无论其他考虑如何:
if (s.StartsWith("0x"))
{
return
s.Skip(2)
.Select((x,i) => new {index = i, value = x})
.GroupBy(pair => pair.index / 2)
.Select(grp => string.Join("", grp.Select(x=>x.value)))
.Select(x => Convert.ToByte(x,16))
.ToArray();
}
但这似乎是您考虑不使用90ish代码的一种解决方案:
public static byte[] ConvertToByteArray(this string s)
{
string tmp = s.Replace("0x","").Replace("-","");
tmp = Regex.Replace(tmp, ".{2}", "$0-");
return tmp.Split('-').Select(b => Convert.ToByte(b, 16)).ToArray();
}