如何组合两个GUID值

时间:2009-09-05 10:54:42

标签: guid

我想组合两个guid值并生成一个32位字母数字值(可以使用散列来完成)。

12 个答案:

答案 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.lytinyurl.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函数将它们串联起来。