我需要根据4个变量的值选择一个aray项,如下所示,在C中。
0 | 1 | 0 | -1 | array[1][0]
-1 | 0 | 1 | 0 | array[1][1]
0 | -1 | 0 | 1 | array[1][2]
1 | 0 | -1 | 0 | array[1][3]
1 | 0 | 0 | -1 | array[2][0]
1 | 0 | 0 | 1 | array[2][1]
-1 | 0 | 0 | 1 | array[2][2]
-1 | 0 | 0 | -1 | array[2][3]
0 | 1 | -1 | 0 | array[3][0]
0 | 1 | 1 | 0 | array[3][1]
0 | -1 | 1 | 0 | array[3][2]
0 | -1 | -1 | 0 | array[3][3]
(数组中第二列的顺序并不重要,如果需要可以重新排序。)
虽然可以(并且完全可以接受)将所有可能性都固定在12个链接if
中,但我想看看是否有人能想出一个“更清洁”的解决方案。
编辑:澄清:我想要一个函数f(a,b,c,d)
,其中(例如)f(0, 1, 0, -1)
会返回array[1][0]
中保存的值。
答案 0 :(得分:3)
我已经用一种方式来描述这种解决方案,其效率略低于使其更容易解释的方式;更简洁的版本很容易从我在这里展示的内容中得到。
将值-1,0和1映射到0x00,0x01和0x02,并将每个值使用2位存储为8位值,例如,您的数组值对应于以下数字:
array[1][0]: binary value 01100100 = 0x64
array[1][1]: binary value 00011001 = 0x19
array[1][2]: binary value 01000110 = 0x46
array[1][3]: binary value 10010001 = 0x91
为所有255个可能的值创建一个数组,这些值可以保存在8位值中(请注意,不会使用某些条目,即任何两个位都设置为1 - 这就是我提到的低效率。)< / p>
所以,例如
array[0] points to the appropriate array for -1, -1, -1, -1
array[1] points to the appropriate array for -1, -1, -1, 0
array[2] points to the appropriate array for -1, -1, -1, 1
array[3] points nowhere
array[4] points to the appropriate array for -1, -1, 0, -1
array[5] points to the appropriate array for -1, -1, 0, 0
array[6] points to the appropriate array for -1, -1, 0, 1
array[7] points nowhere
(etc, obviously)
然后你只需要一个没有循环的单一查找来获得正确的数组(或者你想要的任何东西)。
在更简洁的解决方案中,该表没有指向任何地方的条目。
编辑:
在这种情况下,对于上面的数组,所需的函数是:
f(a,b,c,d) {
return array[(a+1) << 6 + (b+1) << 4 + (c+1) << 2 + (d+1)];
}
答案 1 :(得分:2)
修改你的思维方式并认识到数组是一个函数,从一组索引到一组值。看着这种方式,你会想要像这样定义你的数组:
array[0][1][0][-1] = value currently in array[1][0]
array[-1][0][1][0] = value currently in array[1][1]
etc
现在,不幸的是C不能直接索引具有任意整数范围的数组,但你可以通过以下两种方式之一来解决这个问题:
one=1,zero=0,minusone=2
等常量并使用数组表达式中的常量; 在这两个中,前者可能更可取。
最后,这个数组将包含不在表中的值的条目,你必须在其中加入某种空代码。
答案 2 :(得分:1)
将您发布的表放在数组中,然后在循环中搜索正确的条目。这样您就可以将数据编码为数据而不是代码。
一旦映射规范发生变化,任何更聪明的方法都会产生过度的维护工作。除非证明循环的性能不高,否则我会使用循环。
答案 3 :(得分:0)
除@James McLeod和@High Performance Mark建议的方法外,您还可以使用自动生成的switch
语句:
f(a,b,c,d) {
switch(ind(a,b,c,d)) {
# include "cases.h"
default: assert(0);
};
}
ind()
:
enum { BASE = 3 };
int ind(int a, int b, int c, int d) {
// ind() should produce the same result as the one from the script (see below)
return (BASE*(BASE*(BASE*(a+1) + b+1) + c+1) + d+1);
}
cases.h
:
case 48: return array[1][0];
case 16: return array[1][1];
case 32: return array[1][2];
case 64: return array[1][3];
case 66: return array[2][0];
case 68: return array[2][1];
case 14: return array[2][2];
case 12: return array[2][3];
case 46: return array[3][0];
case 52: return array[3][1];
case 34: return array[3][2];
case 28: return array[3][3];
cases.h
可以通过以下脚本生成:
#!/usr/bin/env python
import csv, fileinput
# parse stdin or file(s) given at command-line as csv-file
rows = ((map(int, row[:-1]), row[-1])
for row in csv.reader(fileinput.input(), delimiter='|') if row)
# function that arranges indexes in C-order
# . any function that produces unique integers will do
# . -1 <= n <= 1
ind = lambda args, base=3: reduce(lambda acc, n: base*acc + (n+1), args, 0)
# print cases for switch(ind(a,b,c,d)) statement
print '\n'.join("case %d: return %s;" % (ind(indexes), value)
for indexes, value in rows if value)
该脚本接受您问题中的表格作为输入。