第一次发布者,刚好在JavaScript / jQuery / Raphael新手之上。请原谅我的过犯。 :)

因此,我一直在寻找问题的答案,并找到了一些有前途的线索,但是我的编程技能太环保了,无法将它们组合在一起。我已经与拉斐尔(Raphael)建立了互动式美国地图,并为用户提供了13个复选框,这些复选框最终可以根据各种条件突出显示各州。每个复选框与大约3至15个状态(当然,所有路径)相关联。当用户选择几个复选框时,我需要找到数组的交集并仅突出显示那些状态。例如:

<input id="a1" value="arr1" type="checkbox" />
<input id="a2" value="arr2" type="checkbox" />
<input id="a3" value="arr3" type="checkbox" />
<input id="a4" value="arr4" type="checkbox" />
<input id="a5" value="arr5" type="checkbox" />

arr1 = [a,b,c];
arr2 = [b,c,d];
arr3 = [b,c,e];
arr4 = [a,e];
arr5 = [a,b];


例如,如果用户选择a1,a2和a3,那么我将为交点创建另一个数组-假设intArr = [b,c]-然后在适当的Raphael上更改填充颜色路径。

我能够通过蛮力解决此问题,这要归功于我在这里找到的巧妙的交集功能。但是,对于一个更优雅的解决方案,实际上节省了大约100行代码,我想我需要根据用户选择创建一个数组数组(或对象?),然后对其进行迭代以将第一个数组与任何数组进行比较主阵列中的其他阵列。有一个陷阱:我想我需要所有的数组都是Raphael元素变量。 (除非我需要为每个元素提供一个ID,然后以某种方式将它们作为目标以更改fill属性?)

这是我的工作方式:

var selectedStates = new Array();
var arr1 = new Array(stArr1,stArr2,stArr3,stArr4,stArr5,stArr6);
var arr2 = new Array(stArr2,stArr3,stArr7,stArr9);
// etc.

var arr1Sel = false;
var arr2Sel = false;
// etc.

$('#selecttools input').click(function(){
  // reset all global variables for each feature
  arr1Sel = false;
  arr2Sel = false;
  // etc.

  // find checked boxes and set appropriate globals to true
  $('#selecttools').find(":checked").each(function() {
    if ($(this).val() == 'arr1') { arr1Sel = true; }
    if ($(this).val() == 'arr2') { arr2Sel = true; }
    //etc.

  // now run selectTheStates
  selectTheStates();
});

function selectTheStates() {
  // first reset selectedStates with the default fill color
  for (var i = 0; i < selectedStates.length; i++) {
    selectedStates[i].attr({fill: "#CCB2E5"});
  }
  // setup the intersect filter
  // thank so much, love this one http://jsfiddle.net/i_like_robots/KpCt2/
  $.arrayIntersect = function(a, b) {
    return $.grep(a, function(i) {
      return $.inArray(i, b) > -1;
    });
  }
  // first make a list of selected arrays
  var ourFinalList = new Array();
  // now, the real brute force...nested if statements that have to go!
  if (arr1Sel == true) {
    ourFinalList = arr1;
    if (arr2Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr2) }
    if (arr3Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr3) }
    // etc.
  } else if (arr2Sel == true) {
    ourFinalList = arr2;
    if (arr3Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr3) }
    // etc. lots of nesting here, yuck!
  } else if (arr13Sel == true) {
    ourFinalList = arr13;
  }
  // now paint all the states in our final list with Raphael
  for (var i = 0; i < ourFinalList.length; i++) {
    ourFinalList[i].attr({fill: "#B38CD8"});
  }
  // last step is reset selectedStates
  selectedStates = ourFinalList;
// end selectTheStates
}


信不信由你,这行得通。但是代码很seriously肿,看起来很业余,以至于我都不好意思在这里发布它。但是我真的很想学习如何做到这一点!请帮忙。

我猜想我需要创建一个数组数组,找到该数组中的第一个数组,然后将其与数组中找到的任何其他数组进行比较/相交。但是,我在尝试执行此操作时遇到了一些问题。 1.因为我正在尝试创建实际上是数组的变量数组,所以我似乎正在将数组的值(而不是数组的占位符)推入主数组。也许我需要对象来做到这一点?

非常感谢您提供的任何帮助!

更新

特别感谢David。我终于得到它的工作。我必须弄清楚的一个窍门:

大卫建议我执行以下操作:

var selectedStates = selected.map(function(){return stateArrays [this];});

经过了一些研究,但我发现我需要将返回的值加倍包装,否则整个数组将作为连接器推送。因此,这可行:

var selectedStates = selected.map(function(){return [stateArrays [this]];});

在那之后,我只需要像他建议的那样遍历数组的数组。虽然,我从来没有得到过pop();因某种原因工作。因此,我只是将selectedStates [0]用作交集工具的第一个数组。

再次非常感谢,大卫!

结束更新

最佳答案

首先,您需要某种方法来找出已选择的阵列。

var selected = $(':checkbox:checked').map(function() { return this.value; });
// selected = ['arr1','arr2','arr3'] for instance


我正在使用:checkbox:checked来获取所有选中的复选框,因为您没有显示任何类名或我们可以用来区分感兴趣的复选框的任何内容。使用.box-class:checked#parent :checkbox:checked之类的方法可能会更好。

在这里,您想将阵列名称列表转换为实际阵列列表。就像现在的代码一样,您刚刚创建了一堆名为arr1arr2等的变量。您可能想改用对象的那些属性:

var stateArrays = {
   arr1: [a,b,c],
   arr2: [b,c,d],
   ...
};


这样,您可以通过以下方式访问它们:

var x = stateArrays[myVariable];
// x = [a,b,c] if myVariable = 'arr1'


如果要保留单独的变量,则无论如何都可以创建这样的对象:

var stateArrays = {
   arr1: arr1, // where arr1 is already defined
   ...
};


因此,在您的情况下:

var selectedStates = selected.map(function() { return stateArrays[this]; });
// selectedStates = [[a,b,c],[b,c,d],[c,d,e]] for instance


现在,您只需要遍历数组数组即可得出相交点:

var result = selectedStates.pop();
selectedStates.forEach(function(x) {
   result = $.arrayIntersect(result, x);
});

// result = [c], given the value of selectedStates as above


上面的代码段使用了您在帖子中定义的$.arrayIntersect

10-07 19:07
查看更多