我想组合两个guid值并生成一个32位字母数字值(可以使用散列来完成)。
答案 0 :(得分:8)
不漂亮,但它有效..
private static Guid MungeTwoGuids(Guid guid1, Guid guid2)
{
const int BYTECOUNT = 16;
byte[] destByte = new byte[BYTECOUNT];
byte[] guid1Byte = guid1.ToByteArray();
byte[] guid2Byte = guid2.ToByteArray();
for (int i = 0; i < BYTECOUNT; i++)
{
destByte[i] = (byte) (guid1Byte[i] ^ guid2Byte[i]);
}
return new Guid(destByte);
}
是的,我可以处理我案例中的非独特保证
答案 1 :(得分:8)
如何将Guids分成两个8字节的块,将它们转换为ulong(8字节),XOR将它们组合起来然后连接2个结果。
public static Guid Combine(this Guid x, Guid y)
{
byte[] a = x.ToByteArray();
byte[] b = y.ToByteArray();
return new Guid(BitConverter.GetBytes(BitConverter.ToUInt64(a, 0) ^ BitConverter.ToUInt64(b, 8))
.Concat(BitConverter.GetBytes(BitConverter.ToUInt64(a, 8) ^ BitConverter.ToUInt64(b, 0))).ToArray());
}
答案 2 :(得分:3)
您无法将2个128位GUID转换为16位或32位值并保持唯一性。对于您声明的应用程序(URL中的使用值),这似乎没有意义,因为URL中的给定值可以映射到任意数量的GUID组合。你考虑过这个吗?
最好的方法是使用网址缩短查找,您可以在其中生成唯一ID,并在需要时将其映射到GUID - 类似于bit.ly或tinyurl.com。
答案 3 :(得分:1)
取决于您尝试做的平台和细节。
在.NET / C#中,你可以采取一种非常简单的方法:
var result = g1.GetHashCode() ^ g2.GetHashCode();
答案 4 :(得分:1)
假设您要生成32 字节值,您可以连接GUID,因为它们各自为16 byte 。如果你真的需要32 位值,我看到的唯一解决方案是生成自己的32位值并将相关的GUID存储在数据库中,以便以后检索它们。
答案 5 :(得分:1)
我知道这是一个古老的问题,但是对于那些以后来查看此问题的人来说,这是可行的:
private Guid Xor(Guid g1, Guid g2)
{
var ba1 = g1.ToByteArray();
var ba2 = g2.ToByteArray();
var ba3 = new byte[16];
for (int i = 0; i < 16; i++)
{
ba3[i] = (byte)(ba1[i] ^ ba2[i]);
}
return new Guid(ba3);
}
如果性能不成问题,则这是干净的且易于阅读。由于XOR的性质,如果将结果与其中一个GUID进行XOR,则会获得另一个GUID。
答案 6 :(得分:1)
在.NET Core 3中,我们可以使用Sse2
/ Span<T>
加快处理速度,并避免所有分配。本质上,此代码将Guid
视为2个连续的Int64
值,并对它们执行异或。 SSE2在单处理器指令(SIMD)中执行异或。
public static Guid Xor(this Guid a, Guid b)
{
if (Sse2.IsSupported)
{
var result = Sse2.Xor(Unsafe.As<Guid, Vector128<long>>(ref a), Unsafe.As<Guid, Vector128<long>>(ref b));
return Unsafe.As<Vector128<long>, Guid>(ref result);
}
var spanA = MemoryMarshal.CreateSpan(ref Unsafe.As<Guid, long>(ref a), 2);
var spanB = MemoryMarshal.CreateSpan(ref Unsafe.As<Guid, long>(ref b), 2);
spanB[0] ^= spanA[0];
spanB[1] ^= spanA[1];
return b;
}
答案 7 :(得分:0)
为什么不尝试一个简单的运算符,即AND,OR,XOR等。将两者结合起来。 XOR将是你最好的选择,因为它具有很好的属性,当使用两个输入中的任何一个得到结果时,你将得到另一个。
编辑:刚看过这个解决方案,就有问题了。这些值必须标准化。请查看Vinay's Answer以获得更好的解决方案。
答案 8 :(得分:0)
这是你的单行:
g1.ToByteArray().Concat(g2.ToByteArray()).GetHashCode()
答案 9 :(得分:0)
我确实需要将两个Guids合并在一起以创建第三个Guid。 如果第三个Guid(不一定是唯一的)将是相同的,无论订单如何,两个原始Guid都被提供。 所以我想出了这个:
public static Guid Merge(Guid guidA, Guid guidB)
{
var aba = guidA.ToByteArray();
var bba = guidB.ToByteArray();
var cba = new byte[aba.Length];
for (var ix = 0; ix < cba.Length; ix++)
{
cba[ix] = (byte)(aba[ix] ^ bba[ix]);
}
return new Guid(cba);
}
答案 10 :(得分:0)
function getallchilds($customer_parent_id){
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$downlineChilds =array();
$breakbleIds =array();
$getallchilds = $read->fetchAll("SELECT id , parent FROM (SELECT id , parent from (SELECT * FROM test order by
parent , id) testdata_sorted, (SELECT @pv := '".$customer_parent_id."') initialisation where
find_in_set(parent , @pv) > 0 and @pv := concat(@pv, ',', id) ORDER BY
parent ASC) AS tt");
foreach($getallchilds as $childs) {
$downlineChilds[] = array($customer_parent_id => $childs['id']);
if ($childs['parent'] > $childs['id']) {
$breakbleIds[] = $childs['id'];
}
}
$checkbreakIDS = count($breakbleIds);
if($checkbreakIDS > 0 ){
foreach($breakbleIds as $breakbleId) {
$childrens = getallchilds($breakbleId);
if ($childrens){
$downlineChilds = array_merge($downlineChilds,$childrens);
}
}
return $downlineChilds;
}
else{
return $downlineChilds;
}
}
答案 11 :(得分:0)
public static string Merge(Guid one, Guid two)
{
return new List<Guid>() { one, two }
.OrderBy(x => x.GetHashCode())
.Select(y => y.ToString().ToLowerInvariant())
.Aggregate((a, b) => ${a.ToLowerInvariant()}_{b.ToLowerInvariant()}");
}
因此,在我的情况下,我需要保持顺序,以确保可以不考虑顺序而合并2个Guid。因此,必须订购它们。那是第一步。然后,只需选择要插入字符串的向导,并且为了方便(超级重要),我使用了string.ToLowerInvariant()。然后使用.Aggregate函数将它们串联起来。