How to Combine Two GUID Values - guid

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.

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;
}
}

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);
}

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.

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;
}

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();

I would use an UUID5 (name-based) to combine two GUIDs, see https://stackoverflow.com/a/5657517/7556646
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.

Related

JObject.Parse modifies end of floating point values

var clientString = "{\"max\":1214.704958677686}";
JObject o = JObject.Parse(clientString);
var jsonString = o.ToString();
contents of jsonString:
{
"max": 1214.7049586776859
}
this is both in visualizing the object and in doing ToString(). Note that the 686 has mysteriously been expanded to 6859 (precision added). This is a problem for us because the numbers are not exactly the same, and a hash function over the json later does not match.
#Ilija Dimov is correct--JSON.NET parses JSON floats as doubles by default. If you still want to use JObject instead of creating a full blown POCO for deserialization, you can use a JsonTextReader and set the FloatParseHandling option:
var reader = new JsonTextReader(new StringReader(clientString));
reader.FloatParseHandling = FloatParseHandling.Decimal;
JObject obj = JObject.Load(reader);
Console.WriteLine(obj["max"].Value<decimal>()); // 1214.704958677686
The reason your value is changed is because of the nature of floating point numbers in .NET. The JObject.Parse(clientString) method at some point executes the following line:
double d;
double.TryParse("1214.704958677686", NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d);
where d represents the number that you get in the JObject.
As d is of type double and double is floating point number, you didn't get the value you expect. Read more about Binary floating point and .NET.
There is an option in JSON.NET for parsing floating point numbers as decimals and get the precision you need, but to do that you need to create custom class that matches your json string and deserialize the json. Something like this:
public class MyClass
{
[JsonProperty("max")]
public decimal Max { get; set; }
}
var obj = JsonConvert.DeserializeObject<MyClass>(clientString, new JsonSerializerSettings
{
FloatParseHandling = FloatParseHandling.Decimal
});
By using this code sample, the value of max property won't be changed.
You can experiment this behaviour just by parsing to float, double and decimal:
Assert.AreEqual(1214.705f,float.Parse("1214.704958677686"));
Assert.AreEqual(1214.7049586776859, double.Parse("1214.704958677686"));
Assert.AreEqual(1214.704958677686, decimal.Parse("1214.704958677686"));
So json.net is using double as an intermediate type. You can change this by setting FloatParseHandling option.

Extracting max value in GridView column in a Web Performance Test

This pertains to .NET Web Performance Tests.
If I have an ASP.NET page with a GridView that has a column of ints, how do I write an extraction rule to get the largest int in the column?
I tried creating a custom extraction rule by inheriting from ExtractionRule and in the Extract method using e.Response.HtmlDocument.GetFilteredHtmlTags however, the HtmlTags returned don't seem to expose their innerHtml contents.
Perhaps you can write an extraction rule that gets the whole column, then process the numbers to get their maximum value. Alternatively, use a built-in extraction rule to get the whole column, then write a plugin to get the maximum value. In either case your code should expect a mixture of numbers and other text.
Ben Day has a great blog post containing two types that express similar concerns. TableColumnValueValidator and ExtractRandomValueFromTable.
http://www.benday.com/2013/08/19/validation-extraction-rules-for-visual-studio-2012-web-performance-tests/
In the Extract(object, ExtractionEventArgs), you need to parse the ExtractionEventArgs.Response.BodyString. Ben uses the HtmlAgilityPack library for this. http://www.nuget.org/packages/htmlagilitypack
Something like this is roughly the code you'd need. This is simliar logic to ExtractRandomValueFromTable.
This does not account for thead/tbody or cells that span multiple columns/rows.
HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(e.Response.BodyString);
HtmlNode table = doc.GetElementbyId(TableId); // TableId is a test property
HtmlNodeCollection columns = table.SelectNodes("//th");
int columnIndex = FindColumnIndexByName(columns, ColumnName); // ColumnName is a test property
HtmlNodeCollection rows = table.SelectNodes("//tr")
int maxValue = Int32.MinValue;
foreach(HtmlNode row in rows)
{
HtmlNodeCollection cells = row.SelectNodes("./td");
// Todo check for bounds of cells here
HtmlNode cell = cells[columnIndex];
int value = Int32.MinValue;
Int32.TryParse(cell.InnerText.Trim(), out value);
maxValue = Math.Max(value, maxValue);
}
e.WebTest.Context.Add(ContextParameterName, maxValue);
int FindColumnIndexByName(HtmlNodeCollection columns, string columnName)
{
for(int i=0; i<columns.Count; i++)
if (String.Equals(columns[i].InnerText, columnName, StringComparison.OrdinalIgnoreCase))
{
return i;
}
return -1;
}

How to check characters at a certain position in a string .net

In my project the customer have a card and a 7 letter particular security code is in it. I want to ask 3 letters from that security code by position.
eg. card security code is **57GHY58**
I want to ask what is the Character at 2,4 and 7 position in your security code?
answer is **7H8**
How to generate that question with random postion and how to check it ?
private static int[] GetThreeRandomNumbers()
{
List<int> list = new List<int>();
Random r = new Random();
while (list.Count < 3)
{
int num = r.Next(1, 7);
if (!list.Contains(num))
{
list.Add(num);
}
}
list.Sort();
return list.ToArray();
}
You have a string with indices 0-6. You need to pick 3 indices from that range randomly. The Random class will help you with this, have a look at its method Random.Next(int, int), it will return you a random number from the specified range. Then the only other thing you have to do is skip the indices you have already used.

How use a variable name to point different data types with the same name?

I have 2 List one stores the name of filterable columns(of type DropDown) and another store the values to load in those filterable columns.
List<string> filterableFields = new List<string>() { "A_B", "C_D", "E_F" };
List<string> AB, CD , EF;
Now at the run time I get the data from web service and I have written a function to to extract values for these filterable fields and store the values to 2nd List.
private void prepareListForFilterableColumns(XDocument records)
{
foreach (var currentField in filterableFields)
{
var values = (from xml in records.Descendants(z + "row")
let val = (string)xml.Attribute("ows_" + currentField.Replace("_", "_x0020_"))
where val != ""
orderby val
select val
).Distinct();
switch (currentField)
{
case "A_B": AB = values.ToList(); break;
case "C_D": CD = values.ToList(); break;
}
}
}
Now I was thinking that instead of hard coding the assignment in swtich case block, If I could just use the first List name "A_B" and replace "_" from it to point to my 2nd List and assign values.ToList() to it.
I understand that c# is a static language, So not sure if we can achieve this, but IF I can it will make my function generic.
Thanks a lot in advance for time and help.
Vishal
You could use a dictionary of lists of strings instead of 3 lists to store the values.
Dictionary<string, List<string>> val lists = new Dictionary<string,List<string>>();
And make the keys of the dictionary equal to the filterables: "AB", "CD",..
then, instead of AB you would use valLists["AB"] and could then reference reach list based on a string key.
The other option would be to use reflection but that would be slower and unnecessarily a bit more complicated.

Define dictionary in protocol buffer

I'm new to both protocol buffers and C++, so this may be a basic question, but I haven't had any luck finding answers. Basically, I want the functionality of a dictionary defined in my .proto file like an enum. I'm using the protocol buffer to send data, and I want to define units and their respective names. An enum would allow me to define the units, but I don't know how to map the human-readable strings to that.
As an example of what I mean, the .proto file might look something like:
message DataPack {
// obviously not valid, but something like this
dict UnitType {
KmPerHour = "km/h";
MiPerHour = "mph";
}
required int id = 1;
repeated DataPoint pt = 2;
message DataPoint {
required int id = 1;
required int value = 2;
optional UnitType theunit = 3;
}
}
and then have something like to create / handle messages:
// construct
DataPack pack;
pack->set_id(123);
DataPack::DataPoint pt = pack.add_point();
pt->set_id(456);
pt->set_value(789);
pt->set_unit(DataPack::UnitType::KmPerHour);
// read values
DataPack::UnitType theunit = pt.unit();
cout << theunit.name << endl; // print "km/h"
I could just define an enum with the unit names and write a function to map them to strings on the receiving end, but it would make more sense to have them defined in the same spot, and that solution seems too complicated (at least, for someone who has lately been spoiled by the conveniences of Python). Is there an easier way to accomplish this?
You could use custom options to associate a string with each enum member:
https://developers.google.com/protocol-buffers/docs/proto#options
It would look like this in the .proto:
extend google.protobuf.FieldOptions {
optional string name = 12345;
}
enum UnitType {
KmPerHour = 1 [(name) = "km/h"];
MiPerHour = 2 [(name) = "mph"];
}
Beware, though, that some third-party protobuf libraries don't understand these options.
In proto3, it's:
extend google.protobuf.EnumValueOptions {
string name = 12345;
}
enum UnitType {
KM_PER_HOUR = 0 [(name) = "km/h"];
MI_PER_HOUR = 1 [(name) = "mph"];
}
and to access it in Java:
UnitType.KM_PER_HOUR.getValueDescriptor().getOptions().getExtension(MyOuterClass.name);

Resources