jquery arrays intersect
Asked Answered
C

6

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>
Cordless answered 23/10, 2010 at 10:22 Comment(4)
Would this not be $('#vraagX input:radio:checked').val(); and not checkboxval() ?Flurried
@mplungjan: when i change var valArr1 = $('#vraag1 input:radio:checked').checkboxval(); to var valArr1 = $('#vraag1 input:radio:checked').val(); it doesn't return any valuesCordless
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 wasteFlurried
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.Cordless
B
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];
}
Broil answered 23/10, 2010 at 13:36 Comment(20)
@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...Cordless
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.Broil
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 :Cordless
<input name="vraag2" type="radio" value="2a,1,2,4,5,7,12,13,14,17,17a,19,21,22,23,24,27,28,30,34,35" class="radio advice" id="vraag2-0" /><label for="vraag1-0">eens</label> <br /> <input name="vraag2" type="radio" value="2b,3,8,11,9,15,16,18,20,25,26,29,31,33,35,37,38,6,10,32" class="radio advice" id="vraag2-1" /><label for="vraag1-1">oneens</label> <br /> <input name="vraag2" type="radio" value="2c,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="vraag2-2" /><label for="vraag1-2">maakt mij niet uit</label>Cordless
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.Broil
i modified the first html example, the new one is at: jsfiddle.net/tschardak/zDySwCordless
not same, it is an unique item added afterwards, but it neds to be in the right orderCordless
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.Broil
Oops.. ok if I change the default choices then you can get 6+ duplicates.Broil
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.Cordless
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.Broil
It does seems to work (jsfiddle.net/zDySw/5)... I set the checked combinations you listed above as defaults and I get "30" as a result.Broil
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...Cordless
What is the id of the div you want to reveal? Is it #diet30 for the last example?Broil
exactly, we now get the ids just the way they are defined later on in html for the hidden elements.Cordless
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.Cordless
Oops, replace the map(x... with map(results..Broil
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 IMHOCordless
@fudgey: i'm afraid the saga continues... do you have a moment for another question regarding this?Cordless
Ahhh sorry, What is your question?Broil
E
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]
Excitant answered 22/2, 2012 at 19:40 Comment(0)
T
12

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

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

returns

["a"]
Tingle answered 25/2, 2013 at 9:43 Comment(3)
Amazing! Is this an intended application of .filter?Cohobate
@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.Tingle
The documentation that @Tingle mentioned: api.jquery.com/filter/#filter-selectionFellmonger
W
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]

Weigh answered 25/4, 2013 at 21:4 Comment(3)
I works great but you have a typo error: intersect, not instersectGlutamine
Thanks for the remark :) I have made a correction to the answerWeigh
This intersect function also supports an arbitrary number of arrays, This package jquery-array-utilities can also be installed using bower. I would like like to add a disclaimer that I originally made the plugin :)Weigh
B
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];
}
Broil answered 23/10, 2010 at 13:36 Comment(20)
@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...Cordless
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.Broil
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 :Cordless
<input name="vraag2" type="radio" value="2a,1,2,4,5,7,12,13,14,17,17a,19,21,22,23,24,27,28,30,34,35" class="radio advice" id="vraag2-0" /><label for="vraag1-0">eens</label> <br /> <input name="vraag2" type="radio" value="2b,3,8,11,9,15,16,18,20,25,26,29,31,33,35,37,38,6,10,32" class="radio advice" id="vraag2-1" /><label for="vraag1-1">oneens</label> <br /> <input name="vraag2" type="radio" value="2c,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="vraag2-2" /><label for="vraag1-2">maakt mij niet uit</label>Cordless
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.Broil
i modified the first html example, the new one is at: jsfiddle.net/tschardak/zDySwCordless
not same, it is an unique item added afterwards, but it neds to be in the right orderCordless
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.Broil
Oops.. ok if I change the default choices then you can get 6+ duplicates.Broil
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.Cordless
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.Broil
It does seems to work (jsfiddle.net/zDySw/5)... I set the checked combinations you listed above as defaults and I get "30" as a result.Broil
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...Cordless
What is the id of the div you want to reveal? Is it #diet30 for the last example?Broil
exactly, we now get the ids just the way they are defined later on in html for the hidden elements.Cordless
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.Cordless
Oops, replace the map(x... with map(results..Broil
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 IMHOCordless
@fudgey: i'm afraid the saga continues... do you have a moment for another question regarding this?Cordless
Ahhh sorry, What is your question?Broil
N
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.

Nurserymaid answered 23/2, 2011 at 10:59 Comment(0)
C
-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;
    }
}
Cockayne answered 1/4, 2016 at 11:46 Comment(1)
Care to add an explanation to your code and how does it answer to the OP's question?Geosynclinal

© 2022 - 2024 — McMap. All rights reserved.