2013-03-19 66 views
2

第一次海報,只是剛剛超過JavaScript/jQuery/Raphael新手。請原諒我的任何過失。 :)基於與Raphael,jQuery/JavaScript的用戶選擇數組的交集

所以,我已經看到高和低的答案我的問題,並已找到一些有前途的線索,但我的編程技能太綠,無法將它們放在一起。我已經與拉斐爾建立了互動的美國地圖,並且我給用戶一組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,後來不知怎麼對付它們改變填充屬性)

這是我如何得到它的工作:

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.因爲我試圖創建一個實際上是數組的變量數組,我似乎將數組的值(而不是數組的佔位符)推送到主數組中。也許我需要物體來做到這一點?

非常感謝您提供的幫助!

UPDATE

特別感謝大衛。我終於搞定了。一招我必須弄清楚:

大衛曾建議我做如下:

VAR selectedStates = selected.map(函數(){回報stateArrays [這];});

它花了一些研究,但我想我需要雙重包裝我的返回值或整個數組將推動作爲concat。所以,這工作:

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

之後,我只需要遍歷數組的數組,如他所建議的。雖然,我從來沒有得到流行();因某種原因工作。所以,我剛剛使用selectedStates [0]作爲交集工具的第一個數組。

非常感謝大衛!

結束時更新

回答

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正如您在您的文章中定義它的代碼片段。

+0

哇,感謝大衛的快速反應!這看起來很周到。我會盡快實施它,讓你知道它是如何發展的。 – 2013-03-19 15:19:09

+0

再次感謝所有的幫助,David。我似乎無法得到流行();方法工作。有任何想法嗎?我已經在上面編輯了我的原始帖子並提供了詳細信 – 2013-03-19 18:53:58

+0

我確實得到它的工作。謝謝大衛!我有很多要學習的。我很高興像你這樣的人願意幫助! – 2013-03-19 20:17:47