Sitrecore MinValue - sitecore

I need to sort very large number of item in Sitecore.
So I used negative number, something like this:
item.sortOrder = int.MinValue + someId
minValue = -2147483647
but sitecore sort correctly only for value greater then -2143053648 so there is a difference of 4430001
so now my code is
item.sortOrder = int.MinValue + 4430001 + someId
and it sorts correctly
does anyone ever experienced something like this, am I doing something wrong?

I'm not sure what exactly you are trying to achieve but it would be better to define a public constant for Sitecore SortOrder Minimum value somewhere accessible.
public const int SortOrderMinimumValue = -2143053648;
And then reference like this
item.Fields["__Sortorder"].Value = SortOrderMinimumValue + someId;
That way the minimum value can be accessed any other code and can be altered at one location should you want to change the minimum value for your sorting.
To sort Items by sort order you then will need to do the following
public class ItemComparer : IComparer
{
public int CompareSortOrder(Item item1, Item item2)
{
int sortOrder1;
bool parsed1 = int.TryParse(item1["__Sortorder"], out sortOrder1);
int sortOrder2;
bool parsed2 = int.TryParse(item2["__Sortorder"], out sortOrder2);
if (!parsed1 || !parsed2)
throw new Exception("Sort order value is incorrect type");
if (sortOrder1 < sortOrder2)
return -1;
if (sortOrder1 > sortOrder2)
return 1;
else
return 0;
}
}
And then reference the code when sorting;
var itemComparer = new ItemComparer();
items.Sort(itemComparer.CompareSortOrder);

Related

Using the TList class to reorder multiple fields

int __fastcall ListSortFunc1(void *Item1, void *Item2)
{
MyStruct *item1 = (MyStruct*)Item1;
MyStruct *item2 = (MyStruct*)Item2;
return (item1->string1 < item2->string1) ? (item1->string1 > item2->string1) :
StrToInt64(item1->number1) - StrToInt64(item2->number1);
}
Reading the online documentation, it is not very clear how to use the Sort method.
My need is to reorder two or more fields. Currently, I have to reorder a file where the first field is numeric, the second is the date, the third a string, the fourth still a string.
I did some tests with Excel and with the code that it reports, but I get completely different results.
Can anyone kindly provide me with directions?
TList::Sort() is passed a callback function that is called during sorting to compare pairs of values from the list. The callback is expected to conform to the specification of the TListSortCompare type. Per its documentation:
Item1 and Item2 are 2 elements from the list. When these are passed to the TListSortCompare function, the Sort method is asking which order they should be in. The comparison returns a value determined by the relative values of Item1 and Item2, as shown in this table:
Value
Description
>0 (positive)
Item1 is greater than Item2
0
Item1 is equal to Item2
<0 (negative)
Item1 is less than Item2
Your function does not satisfy that requirement.
When item1->string1 is less than item2->string1, you are returning 0 when you should be returning a negative value.
Otherwise, you return the result of subtracting item2->number1 from item1->number1. But you are comparing the number1 fields when item1->string1 is greater than or equal to item2->string1. You should be comparing the number1 fields only when the string1 fields are equal. Also, you are risking overflows by using subtraction if the number1 fields have large values.
Try something more like this instead:
int __fastcall ListSortFunc1(void *Item1, void *Item2)
{
MyStruct *item1 = static_cast<MyStruct*>(Item1);
MyStruct *item2 = static_cast<MyStruct*>(Item2);
if (item1->string1 == item2->string1)
{
// simply subtracting the values could lead to integer overflows
// for large values, so just compare the values as-is...
// Also: why are these not stored as __int64 to begin with?
__int64 int1 = StrToInt64(item1->number1);
__int64 int2 = StrToInt64(item2->number1);
if (int1 < int2) return -1;
if (int1 > int2) return 1;
return 0;
}
else
{
return (item1->string1 < item2->string1) ? -1 : 1;
// or:
return CompareStr(item1->string1, item2->string1); // case sensitive
// or:
return CompareText(item1->string1, item2->string1); // case insensitive
}
}

How do I implement linear probing in C++?

I'm new to Hash Maps and I have an assignment due tomorrow. I implemented everything and it all worked out fine, except for when I get a collision. I cant quite understand the idea of linear probing, I did try to implement it based on what I understood, but the program stopped working for table size < 157, for some reason.
void hashEntry(string key, string value, entry HashTable[], int p)
{
key_de = key;
val_en = value;
for (int i = 0; i < sizeof(HashTable); i++)
{
HashTable[Hash(key, p) + i].key_de = value;
}
}
I thought that by adding a number each time to the hash function, 2 buckets would never get the same Hash index. But that didn't work.
A hash table with linear probing requires you
Initiate a linear search starting at the hashed-to location for an empty slot in which to store your key+value.
If the slot encountered is empty, store your key+value; you're done.
Otherwise, if they keys match, replace the value; you're done.
Otherwise, move to the next slot, hunting for any empty or key-matching slot, at which point (2) or (3) transpires.
To prevent overrun, the loop doing all of this wraps modulo the table size.
If you run all the way back to the original hashed-to location and still have no empty slot or matching-key overwrite, your table is completely populated (100% load) and you cannot insert more key+value pairs.
That's it. In practice it looks something like this:
bool hashEntry(string key, string value, entry HashTable[], int p)
{
bool inserted = false;
int hval = Hash(key, p);
for (int i = 0; !inserted && i < p; i++)
{
if (HashTable[(hval + i) % p].key_de.empty())
{
HashTable[(hval + i) % p].key_de = key;
}
if (HashTable[(hval + i) % p].key_de == key)
{
HashTable[(hval + i) % p].val_en = value;
inserted = true;
}
}
return inserted;
}
Note that expanding the table in a linear-probing hash algorithm is tedious. I suspect that will be forthcoming in your studies. Eventually you need to track how many slots are taken so when the table exceeds a specified load factor (say, 80%), you expand the table, rehashing all entries on the new p size, which will change where they all end up residing.
Anyway, hope it makes sense.

Multiple ranges for QDoubleSpinBoxes in QT

I am building an application that makes use of multiple frequency ranges. I need the user to be able to increase/decrease the values in the QDoubleSpinBox, as well as type in the value. If I increase the value to a number out of one range, I would like the value to jump to the next range (same principle for decreasing a value).
Does a QDoubleSpinBox provide this kind of behavior? I can't seem to find an answer for what I'm looking for. I've tried setting a range using QDoubleValidator, but I don't think it supports multiple ranges (unless I'm missing something). I've also tried using range checks with if statements with the valueChanged() signal that gets emitted, but there must be a simpler way, right?
Here's an example of how I'd like the doubleSpinBox to behave:
Starting Value: 9.75
Range 1: 9.75 - 9.95
Range 2: 10.15 - 10.40
Range 3: 17.2 - 20.4
If value goes above 9.95, jump to 10.15.
If value goes above 10.40, jump to 17.2, etc.
I would also like to have the same behavior when decreasing the value (jumping back down to Range 1 if value drops below 10.15).
I would like to do this without writing multiple if/else if statements if I can avoid it.
Trying to create multiple ranges is not a good solution. You should consider your problem in a different way: you have a single range from 9.75 to 20.40 with forbidden values.
So, if you override method such as QDoubleSpinBox::stepsBy() and QDoubleSpinBox::valueFromText(), you will be able to discard the values outside your ranges:
class Spinbox: public QDoubleSpinBox
{
public:
Spinbox(): QDoubleSpinBox()
{
setRange(9.75, 20.4);
setSingleStep(0.1);
}
virtual void stepBy(int steps) override
{
double const newValue = checkValue(value() + (steps * singleStep()));
setValue(newValue);
}
virtual double valueFromText(QString const& text) const override
{
qDebug() << text;
double const newValue = QDoubleSpinBox::valueFromText(text);
return checkValue(newValue);
}
double checkValue(double newValue) const
{
qDebug() << newValue << value();
if (9.95 < newValue && newValue < 10.15)
{
if (newValue > value())
return 10.15;
else
return 9.95;
}
else if (10.4 < newValue && newValue < 17.2)
{
if (newValue > value())
return 17.2;
else
return 10.4;
}
return newValue;
}
};

How do I delete the least recently accessed key in an associative array?

I have an associative array limited to x amount of keys and want to remove the least recently accessed key in order to add another. I found HashAA in mintl which would be able to do the job in D1 but I've found nothing for D2. Is there anything that supports this now or would I need to maintain a second array to get the job done?
I don't have a real answer but I thought it would be fun to try and implement it in a few minutes (it's probably very inefficient and maybe buggy):
import std.stdio;
import std.traits;
struct MyHash(AA, size_t Limit)
if (isAssociativeArray!AA)
{
alias KeyType!AA Key;
alias ValueType!AA Value;
void opIndexAssign(Value value, Key key)
{
if (hash.length >= Limit)
{
Key leastUsed = leastUsedKey;
hash.remove(leastUsed);
counts.remove(leastUsed);
}
hash[key] = value;
}
Value opIndex(Key key)
{
counts[key]++;
return hash[key];
}
Value[Key] hash;
alias hash this;
private:
#property Key leastUsedKey()
{
Key result;
size_t maxCount = size_t.max;
foreach (key; hash.byKey)
{
if (auto count = key in counts)
{
if (*count < maxCount)
{
maxCount = *count;
result = key;
}
}
else
{
return key;
}
}
return result;
}
size_t[Key] counts;
}
// just to avoid declaring variables in main()
#property void consume(int key) { }
void main()
{
MyHash!(int[int], 3) hash;
hash[0] = 0;
hash[1] = 0;
hash[2] = 0;
writeln(hash.keys);
hash[2].consume;
hash[5] = 0;
writeln(hash.keys); // 2 stays, 5 added
hash.clear();
hash[0] = 0;
hash[1] = 0;
hash[2] = 0;
hash[0].consume;
hash[1].consume;
hash[1].consume;
hash[2].consume;
hash[2].consume;
hash[2].consume;
hash[5] = 0;
writeln(hash); // (0 removed)
}
The built in AAs will rehash when they need to in order to fit more elements, are not fixed in size, and will not keep track of how you've accessed or added elements, and because the language has AAs built in, alternate hash table implementations are going to be relatively rare (most everyone just uses the built in AAs).
So, I'm pretty darn sure that you would need to do this yourself - probably by creating a wrapper around the built in AA type and having the wrapper keep track of all of the accesses to it so that it knows which key was accessed least recently.
You could always check out dcollections for some alternate container implemenations (and IIRC it does have a hash table in it, but I doubt that it does what you want). Personally, I've never even heard of a hash table that acted the way that you want it to, so I expect that what you're looking for is at least somewhat abnormal. But it should be simple enough to create a wrapper around AAs which acts the way that you want.

Finding a nonexisting key in a std::map

Is there a way to find a nonexisting key in a map?
I am using std::map<int,myclass>, and I want to automatically generate a key for new items. Items may be deleted from the map in different order from their insertion.
The myclass items may, or may not be identical, so they can not serve as a key by themself.
During the run time of the program, there is no limit to the number of items that are generated and deleted, so I can not use a counter as a key.
An alternative data structure that have the same functionality and performance will do.
Edit
I trying to build a container for my items - such that I can delete/modify items according to their keys, and I can iterate over the items. The key value itself means nothing to me, however, other objects will store those keys for their internal usage.
The reason I can not use incremental counter, is that during the life-span of the program they may be more than 2^32 (or theoretically 2^64) items, however item 0 may theoretically still exist even after all other items are deleted.
It would be nice to ask std::map for the lowest-value non-used key, so i can use it for new items, instead of using a vector or some other extrnal storage for non-used keys.
I'd suggest a combination of counter and queue. When you delete an item from the map, add its key to the queue. The queue then keeps track of the keys that have been deleted from the map so that they can be used again. To get a new key, you first check if the queue is empty. If it isn't, pop the top index off and use it, otherwise use the counter to get the next available key.
Let me see if I understand. What you want to do is
look for a key.
If not present, insert an element.
Items may be deleted.
Keep a counter (wait wait) and a vector. The vector will keep the ids of the deleted items.
When you are about to insert the new element,look for a key in the vector. If vector is not empty, remove the key and use it. If its empty, take one from the counter (counter++).
However, if you neveer remove items from the map, you are just stuck with a counter.
Alternative:
How about using the memory address of the element as a key ?
I would say that for general case, when key can have any type allowed by map, this is not possible. Even ability to say whether some unused key exists requires some knowledge about type.
If we consider situation with int, you can store std::set of contiguous segments of unused keys (since these segments do not overlap, natural ordering can be used - simply compare their starting points). When a new key is needed, you take the first segment, cut off first index and place the rest in the set (if the rest is not empty). When some key is released, you find whether there are neighbour segments in the set (due to set nature it's possible with O(log n) complexity) and perform merging if needed, otherwise simply put [n,n] segment into the set.
in this way you will definitely have the same order of time complexity and order of memory consumption as map has independently on requests history (because number of segments cannot be more than map.size()+1)
something like this:
class TKeyManager
{
public:
TKeyManager()
{
FreeKeys.insert(
std::make_pair(
std::numeric_limits<int>::min(),
std::numeric_limits<int>::max());
}
int AlocateKey()
{
if(FreeKeys.empty())
throw something bad;
const std::pair<int,int> freeSegment=*FreeKeys.begin();
if(freeSegment.second>freeSegment.first)
FreeKeys.insert(std::make_pair(freeSegment.first+1,freeSegment.second));
return freeSegment.first;
}
void ReleaseKey(int key)
{
std:set<std::pair<int,int>>::iterator position=FreeKeys.insert(std::make_pair(key,key)).first;
if(position!=FreeKeys.begin())
{//try to merge with left neighbour
std::set<std::pair<int,int>>::iterator left=position;
--left;
if(left->second+1==key)
{
left->second=key;
FreeKeys.erase(position);
position=left;
}
}
if(position!=--FreeKeys.end())
{//try to merge with right neighbour
std::set<std::pair<int,int>>::iterator right=position;
++right;
if(right->first==key+1)
{
position->second=right->second;
FreeKeys.erase(right);
}
}
}
private:
std::set<std::pair<int,int>> FreeKeys;
};
Is there a way to find a nonexisting
key in a map?
I'm not sure what you mean here. How can you find something that doesn't exist? Do you mean, is there a way to tell if a map does not contain a key?
If that's what you mean, you simply use the find function, and if the key doesn't exist it will return an iterator pointing to end().
if (my_map.find(555) == my_map.end()) { /* do something */ }
You go on to say...
I am using std::map, and
I want to automatically generate a key
for new items. Items may be deleted
from the map in different order from
their insertion. The myclass items may, or may not be identical, so they can not serve as a key by themself.
It's a bit unclear to me what you're trying to accomplish here. It seems your problem is that you want to store instances of myclass in a map, but since you may have duplicate values of myclass, you need some way to generate a unique key. Rather than doing that, why not just use std::multiset<myclass> and just store duplicates? When you look up a particular value of myclass, the multiset will return an iterator to all the instances of myclass which have that value. You'll just need to implement a comparison functor for myclass.
Could you please clarify why you can not use a simple incremental counter as auto-generated key? (increment on insert)? It seems that there's no problem doing that.
Consider, that you decided how to generate non-counter based keys and found that generating them in a bulk is much more effective than generating them one-by-one.
Having this generator proved to be "infinite" and "statefull" (it is your requirement), you can create a second fixed sized container with say 1000 unused keys.
Supply you new entries in map with keys from this container, and return keys back for recycling.
Set some low "threshold" to react on key container reaching low level and refill keys in bulk using "infinite" generator.
The actual posted problem still exists "how to make efficient generator based on non-counter". You may want to have a second look at the "infinity" requirement and check if say 64-bit or 128-bit counter still can satisfy your algorithms for some limited period of time like 1000 years.
use uint64_t as a key type of sequence or even if you think that it will be not enough
struct sequence_key_t {
uint64_t upper;
uint64_t lower;
operator++();
bool operator<()
};
Like:
sequence_key_t global_counter;
std::map<sequence_key_t,myclass> my_map;
my_map.insert(std::make_pair(++global_counter, myclass()));
and you will not have any problems.
Like others I am having difficulty figuring out exactly what you want. It sounds like you want to create an item if it is not found. sdt::map::operator[] ( const key_type& x ) will do this for you.
std::map<int, myclass> Map;
myclass instance1, instance2;
Map[instance1] = 5;
Map[instance2] = 6;
Is this what you are thinking of?
Going along with other answers, I'd suggest a simple counter for generating the ids. If you're worried about being perfectly correct, you could use an arbitrary precision integer for the counter, rather than a built in type. Or something like the following, which will iterate through all possible strings.
void string_increment(std::string& counter)
{
bool carry=true;
for (size_t i=0;i<counter.size();++i)
{
unsigned char original=static_cast<unsigned char>(counter[i]);
if (carry)
{
++counter[i];
}
if (original>static_cast<unsigned char>(counter[i]))
{
carry=true;
}
else
{
carry=false;
}
}
if (carry)
{
counter.push_back(0);
}
}
e.g. so that you have:
std::string counter; // empty string
string_increment(counter); // now counter=="\x00"
string_increment(counter); // now counter=="\x01"
...
string_increment(counter); // now counter=="\xFF"
string_increment(counter); // now counter=="\x00\x00"
string_increment(counter); // now counter=="\x01\x00"
...
string_increment(counter); // now counter=="\xFF\x00"
string_increment(counter); // now counter=="\x00\x01"
string_increment(counter); // now counter=="\x01\x01"
...
string_increment(counter); // now counter=="\xFF\xFF"
string_increment(counter); // now counter=="\x00\x00\x00"
string_increment(counter); // now counter=="\x01\x00\x00"
// etc..
Another option, if the working set actually in the map is small enough would be to use an incrementing key, then re-generate the keys when the counter is about to wrap. This solution would only require temporary extra storage. The hash table performance would be unchanged, and the key generation would just be an if and an increment.
The number of items in the current working set would really determine if this approach is viable or not.
I loved Jon Benedicto's and Tom's answer very much. To be fair, the other answers that only used counters may have been the starting point.
Problem with only using counters
You always have to increment higher and higher; never trying to fill the empty gaps.
Once you run out of numbers and wrap around, you have to do log(n) iterations to find unused keys.
Problem with the queue for holding used keys
It is easy to imagine lots and lots of used keys being stored in this queue.
My Improvement to queues!
Rather than storing single used keys in the queue; we store ranges of unused keys.
Interface
using Key = wchar_t; //In my case
struct Range
{
Key first;
Key last;
size_t size() { return last - first + 1; }
};
bool operator< (const Range&,const Range&);
bool operator< (const Range&,Key);
bool operator< (Key,const Range&);
struct KeyQueue__
{
public:
virtual void addKey(Key)=0;
virtual Key getUniqueKey()=0;
virtual bool shouldMorph()=0;
protected:
Key counter = 0;
friend class Morph;
};
struct KeyQueue : KeyQueue__
{
public:
void addKey(Key)override;
Key getUniqueKey()override;
bool shouldMorph()override;
private:
std::vector<Key> pool;
friend class Morph;
};
struct RangeKeyQueue : KeyQueue__
{
public:
void addKey(Key)override;
Key getUniqueKey()override;
bool shouldMorph()override;
private:
boost::container::flat_set<Range,std::less<>> pool;
friend class Morph;
};
void morph(KeyQueue__*);
struct Morph
{
static void morph(const KeyQueue &from,RangeKeyQueue &to);
static void morph(const RangeKeyQueue &from,KeyQueue &to);
};
Implementation
Note: Keys being added are assumed to be key not found in queue
// Assumes that Range is valid. first <= last
// Assumes that Ranges do not overlap
bool operator< (const Range &l,const Range &r)
{
return l.first < r.first;
}
// Assumes that Range is valid. first <= last
bool operator< (const Range &l,Key r)
{
int diff_1 = l.first - r;
int diff_2 = l.last - r;
return diff_1 < -1 && diff_2 < -1;
}
// Assumes that Range is valid. first <= last
bool operator< (Key l,const Range &r)
{
int diff = l - r.first;
return diff < -1;
}
void KeyQueue::addKey(Key key)
{
if(counter - 1 == key) counter = key;
else pool.push_back(key);
}
Key KeyQueue::getUniqueKey()
{
if(pool.empty()) return counter++;
else
{
Key key = pool.back();
pool.pop_back();
return key;
}
}
bool KeyQueue::shouldMorph()
{
return pool.size() > 10;
}
void RangeKeyQueue::addKey(Key key)
{
if(counter - 1 == key) counter = key;
else
{
auto elem = pool.find(key);
if(elem == pool.end()) pool.insert({key,key});
else // Expand existing range
{
Range &range = (Range&)*elem;
// Note at this point, key is 1 value less or greater than range
if(range.first > key) range.first = key;
else range.last = key;
}
}
}
Key RangeKeyQueue::getUniqueKey()
{
if(pool.empty()) return counter++;
else
{
Range &range = (Range&)*pool.begin();
Key key = range.first++;
if(range.first > range.last) // exhausted all keys in range
pool.erase(pool.begin());
return key;
}
}
bool RangeKeyQueue::shouldMorph()
{
return pool.size() == 0 || pool.size() == 1 && pool.begin()->size() < 4;
}
void morph(KeyQueue__ *obj)
{
if(KeyQueue *queue = dynamic_cast<KeyQueue*>(obj))
{
RangeKeyQueue *new_queue = new RangeKeyQueue();
Morph::morph(*queue,*new_queue);
obj = new_queue;
}
else if(RangeKeyQueue *queue = dynamic_cast<RangeKeyQueue*>(obj))
{
KeyQueue *new_queue = new KeyQueue();
Morph::morph(*queue,*new_queue);
obj = new_queue;
}
}
void Morph::morph(const KeyQueue &from,RangeKeyQueue &to)
{
to.counter = from.counter;
for(Key key : from.pool) to.addKey(key);
}
void Morph::morph(const RangeKeyQueue &from,KeyQueue &to)
{
to.counter = from.counter;
for(Range range : from.pool)
while(range.first <= range.last)
to.addKey(range.first++);
}
Usage:
int main()
{
std::vector<Key> keys;
KeyQueue__ *keyQueue = new KeyQueue();
srand(time(NULL));
bool insertKey = true;
for(int i=0; i < 1000; ++i)
{
if(insertKey)
{
Key key = keyQueue->getUniqueKey();
keys.push_back(key);
}
else
{
int index = rand() % keys.size();
Key key = keys[index];
keys.erase(keys.begin()+index);
keyQueue->addKey(key);
}
if(keyQueue->shouldMorph())
{
morph(keyQueue);
}
insertKey = rand() % 3; // more chances of insert
}
}