'Check if an array is present in a set of arrays
I have fixed-length arrays like this:
char x[10] = "abcdefghij"; // could also contain non-printable char
How to efficiently test if this array is present or not in a fixed set of 10,000 arrays of the same length? (note: these arrays are either all of them binary data arrays, or all of them null-terminated strings, this is fixed at the beginning)
In Python, I would use a set/hashtable/dict and not a list (because of very fast O(1) lookup):
s = "abcdefghij"
S = {"foo1234567", "bar1234567", ..., "baz9876543"}
print(s in S) # True or False
How to do the equivalent in C? (not C++)
Note: the linked question How to check if a string is in an array of strings in C? is about a naive way to do it, with no performance requirement (they loop over all strings and use strcmp). Here it's different since there are 10k arrays, one needs to use another method for performance (a hashtable maybe?).
Solution 1:[1]
The signature of the bsearch function is as follows:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Here, key would be either t1 or t2 and base would be T. nmemb and size would be 9 and 4 respectively.
compar is a pointer to a callback function to do the comparison. This can just be a wrapper around memcmp:
int compare_char4(const void *p1, const void *p2)
{
return memcmp(p1, p2, 4);
}
Then you call bsearch with these parameters:
printf("%s\n", bsearch(t1, T, 9, 4, compare_char4) ? "found" : "not found");
printf("%s\n", bsearch(t2, T, 9, 4, compare_char4) ? "found" : "not found");
Solution 2:[2]
I think the following binary search works (thanks to @WeatherVane) if the array of arrays is sorted, then the complexity is O(log n). We can use memcmp for the comparison.
int binarysearch(unsigned char *T, unsigned char *t, int num, int size) // https://en.wikipedia.org/wiki/Binary_search_algorithm#Algorithm
{
int a = 0;
int b = num-1;
int m, res;
while (a <= b) {
m = (a + b) / 2;
res = memcmp(&T[0] + m*size, &t[0], size);
if (res < 0) {
a = m + 1;
} else if (res > 0) {
b = m - 1;
} else {
return 1;
}
}
return 0;
}
int main()
{
unsigned char T[][4] = {
{ 0x00, 0x6e, 0xab, 0xcd },
{ 0xea, 0x6e, 0xab, 0xcd },
{ 0xeb, 0x6e, 0xab, 0xcd },
{ 0xec, 0x6e, 0xab, 0xcd },
{ 0xed, 0x6e, 0xab, 0xcd },
{ 0xef, 0x6e, 0xab, 0xcd },
{ 0xfa, 0x6e, 0xab, 0xcd },
{ 0xfb, 0x6e, 0xab, 0xcd },
{ 0xff, 0x6e, 0xab, 0xcd }
};
unsigned char t1[4] = { 0x33, 0x6e, 0xab, 0xcd };
unsigned char t2[4] = { 0xfb, 0x6e, 0xab, 0xcd };
printf("%s\n", binarysearch(T[0], t1, 9, 4) ? "found" : "not found");
printf("%s\n", binarysearch(T[0], t2, 9, 4) ? "found" : "not found");
}
Result:
not found
found
Solution 3:[3]
Using only DB export to do migration can turn out to be unnecessarily complex. An easy option would be to create REST endpoints in Drupal application to pull content pages as JSON and then consume JSON in kentico to create content.
For example: /api/awards will render all awards pages in Drupal.
For Drupal 8 You can use views REST export to create this endpoint in minutes. For Drupal 7 https://www.drupal.org/project/views_data_export can be used to export content as JSON
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dbush |
| Solution 2 | Basj |
| Solution 3 | Manish yadav |
