javascript - 基于用户选择的数组与 Raphael、jQuery/JavaScript 的交集

标签 javascript jquery arrays raphael

第一次发帖,仅略高于 JavaScript/jQuery/Raphael 新手。请原谅我的任何过犯。 :)

因此,我四处寻找问题的答案,并找到了一些有希望的线索,但我的编程技能太新手了,无法将它们拼凑在一起。我已经与 Raphael 建立了一个交互式美国 map ,我为用户提供了一组 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]——然后更改上的填充颜色适当的拉斐尔路径。

我能够通过蛮力解决这个问题,这要归功于我在这里找到的一个聪明的交集函数。但是对于一个更优雅的解决方案,一个字面上节省了大约 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
}

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

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

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

更新

特别感谢大卫。我终于让它工作了。我必须弄清楚的一个技巧:

David 建议我执行以下操作:

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

这需要一些研究,但我发现我需要双重包装我的返回值,否则整个数组将作为一个 concat 推送。所以,这有效:

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

关于javascript - 基于用户选择的数组与 Raphael、jQuery/JavaScript 的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15502798/

相关文章:

javascript - ES6 中的扩展运算符在旧版 JavaScript 中转换成什么?它比 array.concat 更 coSTLier 吗?

javascript - 如何使用 javascript 获取数组中特定 id 的最后一个值?

javascript - 在 node.js 中模拟 sinon 注入(inject)服务

javascript - onclick 不是调用函数

javascript - 在单页网站中调整浏览器大小时显示其余 div

javascript - JSON 不适用于 OnChange 事件

javascript - 如何改变jquery下拉值

java - float x[] 与 float[] x 有什么区别?

javascript - 捕获双击 Yii 的 CGridView 行

javascript - 文件上传警报后关闭模式弹出窗口