5

I previously posted this question as jquery/javascript: arrays - jquery/javascript: arrays. But since I am a complete beginner I have formulated the question wrong and didn't understand the answers either.... :(

After failing to implement the given solutions I did some more looking around I found out that I need to compare 6 arrays of possible choices and intersect them to finally display only the overlapping values.

So this is, hopely, a clearer formulation:

I have 6 questions/6 groups of radio buttons for answers. Each answer has multiple values (they can range from 1 to 38 items to be displayed in final 'advice'). I am collecting the values of checked radios in arrays. I get 6 arrays.

How do I intersect 6 arrays in order to get one final array containing only intersecting values form all 6 choices? How do I turn items of this final array into selectors?

Can someone please help me? Thank you!

My script looks now like:

(function($){
  $.fn.checkboxval = function(){
      var outArr = [];
      this.filter(':checked').each(function(){
            outArr.push(this.getAttribute("value"));
      });
      return outArr;
  };
})
(jQuery);
$(function(){
  $('#link').click(function(){
    var valArr1 = $('#vraag1 input:radio:checked').checkboxval();
    var valArr2 = $('#vraag2 input:radio:checked').checkboxval();
    var valArr3 = $('#vraag3 input:radio:checked').checkboxval();
    var valArr4 = $('#vraag4 input:radio:checked').checkboxval();
    var valArr5 = $('#vraag5 input:radio:checked').checkboxval();
    var valArr6 = $('#vraag6 input:radio:checked').checkboxval();
// var newArray = $.merge(valArr1, valArr2, valArr3, valArr4, valArr5, valArr6); <- test to see if I can merge them
// $('#output').text(newArray.join(',')); <- test to see if I can join them
//$("#output").html($("#output").html().replace(/,/gi, ',#diet')); <- test to see if I can append text so it looks like the selectors of divs I need to display later
//    return false;
  });
});

my form/inputs looks like:

<input name="vraag1" type="radio" value="1a,4,5,12,13,17a,18,19,22,23,24,26,27,28,29,30,33,38,6" class="radio advice" id="vraag1-0" /><label for="vraag1-0">ja</label>
<br />
<input name="vraag1" type="radio" value="1b,1,2,3,7,8,11,9,14,15,16,17,20,21,25,31,34,35,36,37,10,32" class="radio advice" id="vraag1-1" /><label for="vraag1-1">nee</label>
<br />
<input name="vraag1" type="radio" value="1c,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,17a,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38" class="radio advice" id="vraag1-2" /><label for="vraag1-2">maakt mij niet uit</label>
Community
  • 1
  • 1
tschardak
  • 63
  • 1
  • 1
  • 4
  • Would this not be $('#vraagX input:radio:checked').val(); and not checkboxval() ? – mplungjan Oct 23 '10 at 10:28
  • @mplungjan: when i change var valArr1 = $('#vraag1 input:radio:checked').checkboxval(); to var valArr1 = $('#vraag1 input:radio:checked').val(); it doesn't return any values – tschardak Oct 23 '10 at 11:33
  • Sorry, did you have function checkboxval when I commented???? If so my bad. However it filters and so does the call to it so at least that is a waste – mplungjan Oct 23 '10 at 13:22
  • nevermind. and yes, i agree with you, but lacking the better knowledge i've put it together like that. any hints on how to intersect 6 arrays? thank you. – tschardak Oct 23 '10 at 13:34

6 Answers6

17

With jQuery loaded, you can punch in the console:

a1=[1,2,3]
a2=[2,3,4,5]
$.map(a1,function(a){return $.inArray(a, a2) < 0 ? null : a;})

The output should be:

[2, 3]
user982671
  • 1,063
  • 1
  • 9
  • 10
12

Was just wondering the same thing and came up with this:

$(["a","b"]).filter(["a","c"])

returns

["a"]
Christoph
  • 150
  • 1
  • 5
  • Amazing! Is this an intended application of `.filter`? – David John Smith Mar 21 '13 at 22:55
  • 1
    @david-john-smith The notation above isn't documented, but what is documented is that `.filter` accepts another jQuery object as a parameter. So `$(["a","b"]).filter($(["a","c"]))` is perfectly legal. – Christoph Jun 11 '13 at 07:04
  • 1
    The documentation that @Christoph mentioned: http://api.jquery.com/filter/#filter-selection – allicarn Mar 16 '16 at 21:57
1

If yoou want do do an intersect operation on arrays you can use the jQuery plugin jQuery Array Utilities

Here is an example code line of how to use it:

$.intersect([1, 2, 2, 3], [2, 3, 4, 5, 5])

will return the result [2,3]

  • I works great but you have a typo error: intersect, not instersect – jobima Sep 30 '15 at 09:06
  • Thanks for the remark :) I have made a correction to the answer – Kristian Abrahamsen Mar 06 '16 at 18:43
  • This intersect function also supports an arbitrary number of arrays, This package [jquery-array-utilities](https://libraries.io/bower/jquery-array-utilities) can also be installed using [bower](https://bower.io). I would like like to add a disclaimer that I originally made the plugin :) – Kristian Abrahamsen Nov 28 '16 at 21:31
0

Your question is still very confusing to me.

But it appears you are getting the value from the inputs and trying to combine them. But they are all strings not arrays.

Try just adding the strings together, then breaking them apart using split() (demo)

$('#link').click(function() {
    var radios = '';
    $('input:radio:checked').each(function() {
        radios += $(this).val() + ',';
    })
    // remove last comma & convert to array
    radios = radios.substring(0, radios.length - 1).split(',');
    // do something with the array
    console.debug(radios);
})

Update: Ok, from your demo HTML, I couldn't get 6 duplicates so in the demo I set it to find 3+ matches. I had to write this script to find duplicates in an array I also made it to return an associative object with the number of duplicates. There may be a better method, but this is what I came up with (updated demo):

$(function() {
    $('#link').click(function() {
        var radios = '';
        $('input:radio:checked').each(function() {
            radios += $(this).val() + ',';
        })
        // remove last comma & convert to array
        var results = [],
            dupes = radios
             .substring(0, radios.length - 1)
             .split(',')
             .getDuplicates(),
            arr = dupes[0],
            arrobj = dupes[1],
            minimumDuplicates = 6; // Change this to set minimum # of dupes to find

        // find duplicates with the minimum # required
        for (var i=0; i < arr.length; i++){
            if ( arrobj[arr[i]] >= minimumDuplicates ){
                results.push(arr[i]);
            }
        }

        // Show id of results
        var diets = $.map(results, function(n,i){ return '#diet' + n; }).join(',');
        $(diets).show(); // you can also slideDown() or fadeIn() here
    })
});


/* Find & return only duplicates from an Array
 * also returned is an object with the # of duplicates found
 * myArray = ["ccc", "aaa", "bbb", "aaa", "aaa", "aaa", "aaa", "bbb"];
 * x = myArray.getDuplicates();
 * // x = [ array of duplicates, associative object with # found]
 * // x = [ ['aaa','bbb'] , { 'aaa' : 5, 'bbb' : 2 } ]
 * alert(x[0]) // x[0] = ['aaa','bbb'] & alerts aaa,bbb
 * alert(x[1]['aaa']) // alerts 5;
 */
Array.prototype.getDuplicates = function(sort) {
    var u = {}, a = [], b = {}, c, i, l = this.length;
    for (i = 0; i < l; ++i) {
        c = this[i];
        if (c in u) {
            if (c in b) { b[c] += 1; } else { a.push(c); b[c] = 2; }
        }
        u[c] = 1;
    }
    // return array and associative array with # found
    return (sort) ? [a.sort(), b] : [a, b];
}
Mottie
  • 84,355
  • 30
  • 126
  • 241
  • @fudgey: thanks for you reaction! my aim is to finally get only overlapping values/strings from this 6 inputs. if i understand correctly i need to split the strings, which will give me values?? i wish i knew how to run your code, though... i apologize for my noobness... almost pulling my hair out here... – tschardak Oct 23 '10 at 14:38
  • Did you look at the demo? Also, when you say overlapping, do you mean that all 6 groups need to have the same number?... this is where it gets confusing because your sample HTML (other question) only has one value in the input whereas your code above have a lot more than one. – Mottie Oct 23 '10 at 15:02
  • yes, only a numbers (or more numbers) which occurs in all 6 groups need(s) to be returned. there are 6 groups of radios, second one is : – tschardak Oct 23 '10 at 15:26


  • – tschardak Oct 23 '10 at 15:27
  • What are you doing with the "17" and "17a" are they considered the same? And the reason your question is confusing is like the HTML you just put in the comments.... are those values supposed to represent checked answers? If you put that HTML into the demo, you can only check one radio at a time, so there is no way to get 6 duplicates. – Mottie Oct 23 '10 at 15:43
  • i modified the first html example, the new one is at: http://jsfiddle.net/tschardak/zDySw/ – tschardak Oct 23 '10 at 15:45
  • not same, it is an unique item added afterwards, but it neds to be in the right order – tschardak Oct 23 '10 at 15:47
  • I've updated my answer and the demo. Like I said with that HTML, there is no way to get 6 duplicates so I set the demo to find 3+ duplicates and show that result. – Mottie Oct 23 '10 at 16:22
  • Oops.. ok if I change the default choices then you can get 6+ duplicates. – Mottie Oct 23 '10 at 16:29
  • Wow! Your code looks very promising. But when I run it I do not get the expected results. For example, radio#vraag5-3 / answer 5d has actually only one possible value : 30. Among others, this checked combination: "1c","2c","3b","4b","5d","6b" should return only 30... Maybe we have gone astray with term 'duplicates', they should be overlaps - the items which exist in each of 6 choices. No overlaps = no result. – tschardak Oct 23 '10 at 17:12
  • Well the way I tried to get around it is to add all the results together, then if it find 6 copies of a value, it adds it to the results. If you are using Firebug, you can see the returned values by adding `console.debug(arrobj);` after the `minimumDuplicates` variable. – Mottie Oct 23 '10 at 17:45
  • It does seems to work (http://jsfiddle.net/zDySw/5/)... I set the checked combinations you listed above as defaults and I get "30" as a result. – Mottie Oct 23 '10 at 17:50
  • Indeed! :-)) This is great. Thank you so much. Is there a way to turn the returned result(s) into id selectors to finally display the corresponding divs? In the first instance above, I used: $("#output").html($("#output").html().replace(/,/gi, ',#diet')); to append ",#diet" to them so they look more the selectors of divs I need to display... – tschardak Oct 23 '10 at 22:26
  • What is the id of the div you want to reveal? Is it `#diet30` for the last example? – Mottie Oct 23 '10 at 22:53
  • exactly, we now get the ids just the way they are defined later on in html for the hidden elements. – tschardak Oct 24 '10 at 09:01
  • thanks again, fudgey! i did a quick test in and it doesn't show the hidden divs. i'll put css and the rest of html (containig divs) in fiddle, try again and if it doesn't work post the link. – tschardak Oct 24 '10 at 11:16
  • Oops, replace the `map(x...` with `map(results..` – Mottie Oct 24 '10 at 11:18
  • i didn't see i have to replace x with results, sorry! i replaced ant it works :)) you are the champ, how many credits can i give you for this, it actually counts for at least 3 answers IMHO – tschardak Oct 24 '10 at 11:23
  • @fudgey: i'm afraid the saga continues... do you have a moment for another question regarding this? – tschardak Oct 24 '10 at 14:20
  • Ahhh sorry, What is your question? – Mottie Oct 26 '10 at 02:09
0

See Simplest code for array intersection in javascript for an intersection function. Split the strings with split(",") and do an intersection on the resulting arrays of strings.

Community
  • 1
  • 1
StanleyH
  • 2,734
  • 1
  • 14
  • 8
-1
function intersect(a, b) {
    var aIsShorter = a.length < b.length;
    var shorter = aIsShorter ? a : b;
    var longer = aIsShorter ? b : a;

    return longer.filter(isFoundInOther).filter(isFoundOnce);

    function isFoundInOther(e) {
        return shorter.indexOf(e) !== -1;
    }

    function isFoundOnce(element, index, array) {
        return array.indexOf(element) === index;
    }
}
António Ribeiro
  • 4,129
  • 5
  • 32
  • 49