我走后,他们会给你们加班费,会给你们调休,这并不是他们变好了,而是因为我来过。------龙哥

文章目录
1.
大厂经典的面试题,给你40亿个不重复的无符号整数,让你快速判断一个数是否在这40亿个数中,最直接的思路就是遍历这40亿个整数,逐一进行比对,当然这种方式可以倒是可以,但是效率未免太低了。
另一种方式就是排序+二分的查找,因为二分查找的效率还是比较高的,logN的时间复杂度,但是磁盘上面无法进行排序,排序要支持下标的随机访问,这40亿个整数又无法加载到内存里面,你怎么进行排序呢?所以这样的方式也是不可行的。
那能不能用红黑树或者哈希表呢?红黑树查找的效率是logN,哈希表可以直接映射,查找的效率接近常数次,虽然他们查找的效率确实很快,但是40亿个整数,那就是160亿字节,10亿字节是1GB,16GB字节红黑树和哈希表怎么能存的下呢?这还没有算红黑树的三叉链结构,每个结点有三个指针,而且哈希表每个结点会有一个next指针,算上这些的话需要的内存会更大,所以用红黑树或哈希表也是无法解决问题的。
2.
题目说的是判断在不在,并且都是无符号的整数,也就是正整数,那我们能不能用一个比特位来标识某个数在或不在呢?0标识不存在,1标识存在,这不就能解决问题了吗?所以我们采取位图的方式来解决这个问题。
如果一个数用一个比特位来标识,则42亿多个数就是42亿多个比特位,2的29次方个字节,2的30次方字节是1GB,所以我们开的空间大小就是512MB,申请512MB内存还是够的。

3.
在内存中我们肯定是不能按照bit位来申请内存的,这不符合内存管理的机制,最小申请的内存也是1byte,则在位图里面我们就开出来一个个的char,用每个char的比特位来直接对应数字,这就是直接定址法,第一个char能够表示的数字是0-7,第二个char能够表示的数字是8-15,第三个char能够表示的数字是16-23……以此类推,判断某一个数在第几个char上面/8即可,判断在char上的哪个比特位%8即可,这就完成了位图中对应数字的标识,比特位为1表示这个数字存在,为0表示不存在。

1.
位图的功能主要分为三个函数,对某一比特位的置1 set(),对某一比特位的置0 reset(),对某一比特位是1还是0进行判断test()。
对于set,想要让某一比特位变为1其他位不变,则可以用1按位或对应的比特位,那就只需让1向高位移动j位,然后用位图中对应的char进行按位或等即可。
对于reset,想要让某一比特位变为0其他位不变,则可以用0按位与对应的比特位,那就只需让1向高位移动j位,然后按位取反,最后用位图中对应的char进行按位与等即可。
对于test,我们可以让对应比特位按位与1,其他比特位按位与0,这样其他比特位都是0,如果测试的比特位是1,则结果是非0,那就是true,如果测试的比特位是0,则结果是0,那就是false。
有些编译器下bool值是4个字节,如果是4个字节则返回的时候要发生整型提升,但我的编译器是1个字节,无须整型提升,直接返回即可。
// 非类型模板参数
template <size_t N>
class bitset
{
public:
bitset()
{
_bits.resize(N / 8 + 1, 0);
//可能开的比特位恰好满足数字的个数,也可能最多浪费7个比特位
//_bits.resize(N << 3 + 1, 0);//位运算符优先级过低,这里先进行+运算,则结果和我们预想的不一致,发生错误。
}
void set(size_t x)
{
size_t i = x / 8;
size_t j = x % 8;
_bits[i] |= 1 << j;
}
void reset(size_t x)
{
size_t i = x / 8;
size_t j = x % 8;
_bits[i] &= ~(1 << j);
}
bool test(size_t x)
{
size_t i = x / 8;
size_t j = x % 8;
return _bits[i] & (1 << j);//这里不是&=,因为test不改变位图,只是判断一下而已
//有些编译器bool值是四个字节,返回时会发生整型提升,高位补符号位,但这些都不重要,只要是非0就行,判断为真
//我的编译器bool值是一个字节
}
private:
vector<char> _bits;
};
2.
在位图这里有些老铁容易将其和字节序的大小端混淆,从而在进行比特位移动的时候会产生误解,认为如果是小端,则向高位移动就是向左移动,如果是大端则向高位移动就是向右移动,这是错误的,在移动比特位这里我们不需要考虑这么多,无论是大端机器还是小端机器针对的都是整型的单个字节序,而且只要你用<<那就是向高位移动,用>>就是向低位移动,不要去看方向,而且大端机的数据高位和低位确实和我们日常的习惯不符合,但是CPU会在内存中处理数据,你不需要过多考虑。你只需要记住<<是让数据向地址的高位移动,>>是让数据向地址的低位移动。

3.
下面是位图的测试代码,如果要开42亿多比特位的话,可以用-1转成无符号整数的方式来表示42亿,当然也可以通过语言自带的预定义宏来表示42亿多。
从任务管理器中也可以看到运行进程申请的内存的确是512MB多一些,因为还有其他的信息也需要占用内存。


void test_bitset()
{
cout << "bool的字节大小:" << sizeof(bool) << endl;
//bitset<100> bs1;//0-99的整数判断在不在,开范围大小
bitset<-1> bs2;//用-1转成无符号数代替无符号数的最大数42亿9千万,0xffffffff,INT_MAX是21亿,用UINT_MAX
bs2.set(10);
bs2.set(10000);
bs2.set(99999);
bs2.set(88888);
cout << bs2.test(10) << endl;
cout << bs2.test(10000) << endl;
cout << bs2.test(99) << endl;
cout << bs2.test(100) << endl;
cout << bs2.test(101) << endl;
cout << bs2.test(88888) << endl;
bs2.reset(10000);
bs2.reset(88888);
cout << endl;
cout << bs2.test(10) << endl;
cout << bs2.test(10000) << endl;
cout << bs2.test(99) << endl;
cout << bs2.test(100) << endl;
cout << bs2.test(101) << endl;
cout << bs2.test(88888) << endl;
}
1.
之前是判断整数是否出现,现在是判断只出现一次的整数,那就说明有的整数出现了多次,其实解决起来也很简单,我们只需要开两个位图即可,用两个比特位去标识即可,00代表出现0次,01代表出现1次,10或者11什么的我们就不管了,他们统一表示出现一次以上。
有人可能会觉得100亿个整数太多了,担心位图存不下,别说100亿,就是1000亿,1w亿都能存的下,因为位图存的是一个范围内有多少种数,与数据的个数完全无关,仅仅和数据的范围有关系,所以根本不用担心存不下这样的事情,因为整数最多就42亿多个。

template <size_t N>
class twobitset
{
public:
twobitset()//初始化列表会初始化
{}
void set(size_t x)
{
if (!_bs1.test(x) && !_bs2.test(x))
{
//出现0次,则搞成01
_bs2.set(x);
}
else if(!_bs1.test(x) && _bs2.test(x))
{
//出现1次,则搞成10
_bs1.set(x);
_bs2.reset(x);
}
//10出现1次以上,不需要变他
}
void PrintOnce()
{
for (size_t i = 0; i < N; i++)
{
if (!_bs1.test(i) && _bs2.test(i))
{
//如果是01,说明出现一次,可以打印出来
cout << i << endl;
}
}
}
private:
bitset<N> _bs1;//用的是我们自己写的bitset,编译器优先在wyn命名空间找
bitset<N> _bs2;
};
void test_twobitset()
{
twobitset<100> tbs;
int arr[] = { 3,5,3,99,99,67,45,51,52,52 };
for (auto e : arr)
{
tbs.set(e);
}
tbs.PrintOnce();
}
2.
我们可以开两个位图,分别给两个有100亿整数的文件各自开一个位图,将各个文件中的整数映射到各自的位图当中,然后分别遍历比对两个位图,当两个比特位同时为1时,表示对应的整数同时在两个文件中出现,即为两个文件交集中元素的一员。或者可以分别对两个位图中的每一个char进行按位与,同时为1的比特位会留下,留下的比特位就是文件的交集整数。

3.
这道题和第一个其实是一样的,只不过第一个求的是只出现一次的,这个求的是不超过两次的,那就是出现1次和2次的,也很简单两个比特位的组合即可表示出现次数为0 1 2 2次以上的这四种情况,所以实现起来也比较简单,和第一题一样开两个位图即可解决。

1.
这样的题目典型就是KV模型的问题,即通过key IP找对应的value 出现次数,对于KV模型的问题首先想到的就是用map来统计次数,但是100G大小的文件是无法加载到内存的,所以直接用map是不行的。
有人可能会想到用位图来解决这里的问题,多开几个位图,用多个比特位的组合来表示次数,这样的想法也是不行的,你怎么知道次数最多是几次呢?如果出现次数最多是10w次呢?你要开多少个位图呢?内存够开那么多位图吗?所以这样的方式也是不行的。

2.
既然直接用map存储无法解决,那就间接用map进行存储KV键值对。切分大文件变成小文件,让小文件中的内容能够加载到内存里面,能够用map存储起来。
首先试想一下,平均切分100G文件可以吗?如果平均切分的话,则某些多次出现的IP可能会被散列到不同的子文件当中,每次内存只能加载一个子文件的内容,此时统计出的最多IP次数在大文件中是最多的吗?这当然是不确定的,所以平均切分的方式万万不可行,因为相同的IP有可能在平均切分的过程中被散列到不同的子文件,则会导致每个子文件中出现次数最多的IP是不可靠的。
3.
在切分文件的这一步中就要用到哈希切分了,我们可以将IP进行字符串哈希算法的转换,将其转换为整型,控制映射的范围为0-99,即用转换为整型后的值去%100,那么相同的IP就一定会映射到同一个文件当中,此时每个子文件就相当于一个冲突哈希桶,里面装着的都是出现多次的IP,当然也有可能是只出现一次的IP,反正这些都不重要,只要出现多次的IP没有散列到不同的子文件,分到相同的子文件即可。
此时每个子文件中出现次数最多的IP的次数和在大文件中出现的次数是相同的,则我们只需要一个字符串对象,存储当前子文件中出现次数最多的IP即可,然后依次遍历后面的子文件,若次数大于上一个文件中出现次数最多的IP,那就更新字符串对象即可。

1.
如果哈希切分后的单个子文件还是太大该怎么办呢?
此时要分为两种情况,如果子文件中冲突的IP大多是不相同的IP,那么map是会统计不下的,此时就需要我们换个字符串hashfunc,递归哈希切分这个子文件,可以改变一下哈希函数中除留余数法,模的大小,但除留余数法还是挺好用的,如果你觉得不太好用,你也可以尝试其他的哈希函数,我个人推荐继续使用除留余数法,改变一下模的大小,再换个hashfunc,重新建立映射关系,递归将这个子文件进行哈希切分,直到map能够统计这个子文件中的IP内容为止。
另一种情况就是,如果子文件中冲突的IP大多是相同的IP,此时虽然文件的大小表面上看来很大,map有可能存不下,但是不要忘了,map是可以去重的呀,虽然你文件很大,但是大多数的IP都是重复的IP,map当然是可以存的下的,对于大量出现的IP只需要++对应的出现次数value即可。
2.
具体实现的方案是这样的,上来先遍历子文件内容,将每个内容构造成键值对插入到map里面,如果map存不下,则在插入的过程中会出现内存不够的情况,insert会报错,那其实就是new结点失败,new失败是会抛异常的,我们只要捕获这个异常即可,此时说明这个子文件中大多是不同的IP,那么只需要递归哈希切分这个子文件即可。
如果map能够存的下,则正常统计出 出现次数最多的IP即可,无须进行其他任何操作。

1.
位图是一个个的比特位作为存储内容的vector构成的,他利用了直接定址法的思想,并且每个整数都能映射到位图的唯一位置,不会有哈希冲突的情况发生,而且由于是比特位构成的,那也能突出他空间消耗非常的小。
但位图也有他的缺点,它适用于解决K模型的问题,KV模型用位图解决是不太适合的,并且位图只能针对于整型,对于其他类型无法支持。

2.
对于位图只能解决整型情况下的K模型,而对于字符串这样类型的K模型问题便无法支持的情况,有大佬将哈希和位图结合提出了布隆过滤器。
即 将字符串通过hashfunc转换为整形后通过除留余数法得到哈希地址,但这样的操作势必会出现哈希冲突,因为字符串是无限的,而整数是有限的,在除留余数得到哈希地址的过程中,肯定会有两个字符串同时映射到相同的哈希地址处,这样的情况就是我们所说的哈希冲突,有可能本身insert没有被映射到位图中,但是当test(“insert”)的时候,他的映射位置和sort重合,那么对应的比特位被sort置为1了已经,则insert被误判为存在于位图当中,此时就出现了误判的问题。

3.
我们如何解决布隆过滤器误判的问题呢?首先误判这样的问题肯定是不能消除的,因为不管你hashfunc处理的再好,但字符串是无限的啊,永远都会存在哈希冲突的情况,所以是无法消除这样的问题的,我们只能降低误判的概率,让布隆过滤器对于K模型在不在的问题判断的更加精确一点,想要完全精确这是不可能的。
4.
布隆过滤器判断在是不准确的,但是不在一定是准确的,因为在有可能是他的比特位和其他的字符串冲突了,但是如果判断不在,那相应比特位是0,表示当前test的字符串的的确确是不在的。
在开位图大小这里我们优点无法确定,因为如果用直接映射的话,我们不清楚字符串转换为的整数最大是多少,最小是多少,所以我们用除留余数法来控制位图开多大。

降低误判率就是通过一个字符串通过多个hashfunc映射位图中多个不同的位置,只有多个位置同时为1时才表示存在,有一个为0即表示不存在,这样的方式只能降低误判率,因为有可能多个位置都发生了冲突,两个字符串映射到的三个比特位恰好是相同的,这样的情况也是有可能发生的。

5.
我们如何选择哈希函数个数和布隆过滤器长度呢?
哈希函数选择过多,则布隆过滤器bit位置被置为1的速度就越快,布隆过滤器也会容易误判,哈希函数选择太少的话,误报率也会变高,因为没有其他的选择,各个字符串只有一个bit位,如果冲突,则必然发生误报。
布隆过滤器的长度越短,则很快所有的bit位置就会被置为1,这也会影响布隆过滤器的判断准确性,如果布隆过滤器的长度越长,则误报率其实会越低,因为各个字符串的映射位置会分散开来,不易产生误报,只是空间消耗会上升,所以布隆过滤器的长度也不宜过于长。
6.
如何选择哈希函数个数和布隆过滤器的长度,下面文章进行了详细解释,并贴出了一个公式,假设在3个哈希函数的情况下,如果想要让误报率较低,则在位图中每set一个元素,大概要开4.2个比特位。

布隆过滤器一般适用于不需要准确判断的场景,比如下面列举的昵称判重,查找用户id等情况下,都可以使用布隆过滤器。

1.
布隆过滤器的底层就是用位图来实现的,实现起来还是比较简单的,增加几个hashfunc,多去映射几个位置,在set的时候将多个哈希位置设为1,测试的时候,只要有一个位置是0,则没有必要继续判断下去,返回false即可,当前测试的字符串一定是不存在的。
2.
下面代码中X代表布隆过滤器的长度倍数,即插入N个元素时,布隆过滤器要开的长度为X×N的大小,默认布隆过滤器判断在不在的元素类型为string,如果你想判断其他元素类型,可以自己去传对应的模板参数,但hashfunc也可能需要换一下,需要能够将你所传的类型转为整型。
3.
除4个hashfunc外,你也可以测试3个 5个等等,你也可以改变布隆过滤器的长度倍数等等,进行逐一的测试比较。
struct BKDRHash
{
size_t operator()(const string& key)
{
size_t hash = 0;
for (auto ch : key)
{
hash *= 131;
hash += ch;
}
return hash;
}
};
struct APHash
{
size_t operator()(const string& key)
{
unsigned int hash = 0;
int i = 0;
for (auto ch : key)
{
if ((i & 1) == 0)
{
hash ^= ((hash << 7) ^ (ch) ^ (hash >> 3));
}
else
{
hash ^= (~((hash << 11) ^ (ch) ^ (hash >> 5)));
}
++i;
}
return hash;
}
};
struct DJBHash
{
size_t operator()(const string& key)
{
unsigned int hash = 5381;
for (auto ch : key)
{
hash += (hash << 5) + ch;
}
return hash;
}
};
struct JSHash
{
size_t operator()(const string& s)
{
size_t hash = 1315423911;
for (auto ch : s)
{
hash ^= ((hash << 5) + ch + (hash >> 2));
}
return hash;
}
};
//布隆过滤器不仅可以存字符串,也可以存其他类型,只要最后能转换成整型完成取模映射就行,取模是比较常用的哈希函数
//平均存储一个值,开辟X个比特位
template <size_t N, size_t X = 8, class K = string,
class Hashfunc1 = BKDRHash, class Hashfunc2 = APHash, class Hashfunc3 = DJBHash, class Hashfunc4 = JSHash>
class BloomFilter
{
public:
void set(const K& key)
{
size_t hash1 = Hashfunc1()(key) % (X * N);
size_t hash2 = Hashfunc2()(key) % (X * N);
size_t hash3 = Hashfunc3()(key) % (X * N);
size_t hash4 = Hashfunc4()(key) % (X * N);
_bs.set(hash1);
_bs.set(hash2);
_bs.set(hash3);
_bs.set(hash4);
}
bool test(const K& key)
{
size_t hash1 = Hashfunc1()(key) % (X * N);
if (!_bs.test(hash1))
{
return false;
}
size_t hash2 = Hashfunc2()(key) % (X * N);
if (!_bs.test(hash2))
{
return false;
}
size_t hash3 = Hashfunc3()(key) % (X * N);
if (!_bs.test(hash3))
{
return false;
}
size_t hash4 = Hashfunc4()(key) % (X * N);
if (!_bs.test(hash4))
{
return false;
}
//上面判断不在的情况一定是准确的。
return true;//这里可能会存在误判,多个哈希位置都和别的字符串冲突了
}
private:
std::bitset<N * X> _bs;//如果size_t类型×X过后,size_t类型存不下,也可以选择换long long类型
};
下面是布隆过滤器代码的测试接口,代码难度并不大,你可以看看具体的逻辑,然后进行接口调用即可。
void test_bloomFilter2()
{
srand(time(0));
const size_t N = 10000;
BloomFilter<N> bf;
std::vector<std::string> v1;
std::string url = "https://www.cnblogs.com/-clq/archive/2012/0X/31/2X281X3.html";
for (size_t i = 0; i < N; ++i)
{
v1.push_back(url + std::to_string(i));
}
for (auto& str : v1)
{
bf.set(str);
}
// v2跟v1是相似字符串集,但是不一样
std::vector<std::string> v2;
for (size_t i = 0; i < N; ++i)
{
std::string url = "https://www.cnblogs.com/-clq/archive/2012/0X/31/2X281X3.html";
url += std::to_string(999999 + i);
v2.push_back(url);
}
size_t n2 = 0;
for (auto& str : v2)
{
if (bf.test(str))
{
++n2;
}
}
cout << "相似字符串误判率:" << (double)n2 / (double)N << endl;
// 不相似字符串集
std::vector<std::string> v3;
for (size_t i = 0; i < N; ++i)
{
string url = "zhihu.com";
url += std::to_string(i + rand());//rand()总共只有3w多个不重复的数据,所以测试数据N多了以后,这里+i让其不重复
v3.push_back(url);
}
size_t n3 = 0;
for (auto& str : v3)
{
if (bf.test(str))
{
++n3;
}
}
cout << "不相似字符串误判率:" << (double)n3 / (double)N << endl;
}
1.
布隆过滤器最好不要支持reset接口,因为可能会相互影响。但如果强行支持reset,则可以通过多开位图的方式来实现,用比特位的组合来标识当前比特位的哈希冲突个数,即为计数器的方式来标识,这样可以不影响其他的字符串存储情况。

2.
但如果采用计数方式来实现reset,也就是布隆过滤器的删除,会存在一些问题。比如你不小心将某一个字符串多次重复删除,此时计数会进行- -,但如果是0- -呢?有可能还会发生越界访问等问题。所以计数方式也有他的缺陷,最好不要强制增加布隆过滤器的reset操作。

1.
近似算法其实就是布隆过滤器来实现,将所有的query转换成整数,然后将整数进行除留余数法后完成映射,整数范围最多是42亿,42亿比特位才占用512MB,1G的空间用来开位图一定是够用的,而且我们是可以自己控制位图的大小的,我们想开多大就开多大,我们只开200MB可以吗?当然是可以的,哈希函数的个数,布隆过滤器的长度都是我们自己可以控制的,这是除留余数法给我们带来的最大的好处,因为我们是不清楚字符串转换为整型后是多大的,所以可以通过%N来将他转换后的整型控制在0 - N-1里面。此时将其中一个文件所有的query添加到布隆过滤器中,遍历另一个文件内容,看遍历到的query是否存在于布隆过滤器里面,当然可能会出现误判的情况,但题目要求给出近似算法即可。

2.
对于精确算法来说,核心还是使用哈希切分的思想,将两个大文件分别使用哈希切分,切分成1000个小文件,AB大文件各自遍历query语句,两个大文件的哈希切分函数用的是相同的,相同的query一定会各自进入到对应编号的小文件,然后再分别比对对应的小文件里的query语句,此时进行比对可以用哈希表的方式,先对两个小文件各自去重一下,或者用底层为红黑树的map也可以,因为此时文件已经被哈希切分的很小了,内存可以存的下。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2iu03uh9z2ios
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>
查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s