I want to combine two guid values and generate a 32 bit alphanumberic value(It can be done by using hashing).
Not Pretty, but it works..
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);
}
and yes, I can deal with the non-unique-guarantee in my case
What about splitting the Guids into 2 chunks of 8 bytes each, convert them to ulong (8 bytes), XOR combine them and then concat the 2 results.
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());
}
You can't convert 2 128-bit GUIDs into a 16-bit or 32-bit value and maintain uniqueness. For your stated application (use value in URL) this doesn't seem to make sense, as a given value in the URL could map to any number of GUID combinations. Have you considered this?
The best approach would be to use an URL-shortening lookup where you generate a unique ID and map it to the GUIDs if needed - similarly to bit.ly or tinyurl.com.
I actually did have a need to merge two Guids together to create a third Guid. Where the third Guid (not necessarily unique) would be the same regardless of the order the two original Guids were supplied. So I came up with this:
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);
}
var a = Guid.NewGuid();
var b = Guid.NewGuid();
var hashOfXor = Xor(a, b).GetHashCode();
public static Guid Xor(Guid a, Guid b)
{
unsafe
{
Int64* ap = (Int64*) &a;
Int64* bp = (Int64*) &b;
ap[0] ^= bp[0];
ap[1] ^= bp[1];
return *(Guid*) ap;
}
}
Assuming you want to generate a 32 byte value you can just concatenate the GUIDs since they are 16 byte each. If you really need a 32 bit value the only solution I see is generating your own 32 bit values and storing the related GUIDs in a database so you can retrieve them later.
Depends on the platform and details of what you are trying to do.
In .NET/C# you could jus take avery simple approach:
var result = g1.GetHashCode() ^ g2.GetHashCode();
In .NET Core 3 we can use Sse2
/Span<T>
to speed things up, and avoid all allocations. Essentially this code treats a Guid
as 2 consecutive Int64
values, and performs the xor on them. SSE2 performs the xor in a single processor instruction (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;
}
I would use an UUID5 (name-based) to combine two GUIDs, see https://mcmap.net/q/22029/-how-to-create-deterministic-guids
Guid g1 = new Guid("6164742b-e171-471b-ad6f-f98a78c5557e");
Guid g2 = new Guid("acbc41aa-971c-422a-bd42-bbcefa32ffb4");
Guid g12 = Create(IsoOidNamespace, g1.ToString() + g2.ToString(), 5)
In this example g12
would be: e1ccaee5-ea5e-55c6-89a5-fac02043326e
.
There's no native support in the .NET Framework for creating these, but the code is posted on GitHub that implements the algorithm.
See as well the following .NET Fiddle, https://dotnetfiddle.net/VgHLtz
Why not try a simple operator i.e. AND, OR, XOR etc. To combine the two. XOR would be your best bet hear I would imagine as it has the nice property of when xoring the result with either of the two inputs you will get the other.
Edit: having just looked at this solution, there is a problem with it. The values would have to be normalised. Take a look at Vinay's Answer for a better solution.
Here's a one-liner for you:
g1.ToByteArray().Concat(g2.ToByteArray()).GetHashCode()
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()}");
}
So in my situation i needed to maintain order in order to make sure that the 2 Guids could be merged regardless of order. Therefore they have to be ordered. That was step one. Then, it's simply selecting the guids to string and for consitency (super important), I used string.ToLowerInvariant(). Then concatenated them using the .Aggregate function.
© 2022 - 2024 — McMap. All rights reserved.