Check that the array is unique [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript: Determine whether an array contains a value
var thelist = new Array();
function addlist(){
thelist.push(documentgetElementById('data').innerHTML);
}
How can I check that the data I push does not already exsist in array thelist?

var thelist = []; // Use the array literal, not the constructor.
function addlist(){
// get the data we want to make sure is unique
var data = documentgetElementById('data').innerHTML;
// make a flag to keep track of whether or not it exists.
var exists = false;
// Loop through the array
for (var i = 0; i < thelist.length; i++) {
// if we found the data in there already, flip the flag
if (thelist[i] === data) {
exists = true;
// stop looping, once we have found something, no reason to loop more.
break;
}
}
// If the data doesn't exist yet, push it on there.
if (!exists) {
thelist.push(data);
}
}

If you don't care about IE < 9 you could also use the Array method "some".
Just have a look at this example:
var thelist = [1, 2, 3];
function addlist(data) {
alreadyExists = thelist.some(function (item) {
return item === data
});
if (!alreadyExists) {
thelist.push(data);
}
}
addlist(1);
addlist(2);
addlist(5);
console.log(thelist);​
http://jsfiddle.net/C7PBf/
Some determines whether at least one element with given constraint (callbacks return value === true) does exist or not.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some

If you are not concerned about IE version 8 or lower, you can use Array.filter:
var thelist = new Array();
function addlist(){
var val = documentgetElementById('data').innerHTML;
var isInArray = theList.filter(function(item){
return item != val
}).length > 0;
if (!isInArray)
thelist.push(val);
}
Or, you could use Array.indexOf:
var thelist = new Array();
function addlist(){
var val = documentgetElementById('data').innerHTML;
var isInArray = theList.indexOf(val) >= 0;
if (!isInArray)
thelist.push(val);
}

Have a look at underscore.js : underscore.js
Then you can check the array as
_.contains(thelist, 'value you want to check');
// The full example
var thelist = new Array();
function addlist(){
var data = documentgetElementById('data').innerHTML;
if(!_.contains(thelist, data)) theList.push(data);
}
or you can add the values to the array without concerning the duplicate values, and after the adding process is finished, you can remove the duplicate elements by
theList = _.uniq(theList);
The second method of course less efficient.

Related

How to check each item in an array that contains a specific part of a string

function buildEVQuestionLists(category) {
var items = [];
var mySurvey = SurveyUtil.Surveys.Get(CurrentPID());
var remoteQuestions = mySurvey.Questions;
for (var i = 0; i < remoteQuestions.Count; i++) {
var question = remoteQuestions[i];
if (question.IsInCategory(category)) items.push(question.Id);
}
return items;
}
This is what return items gives:[EV10013,EV10361,EV10022,EV10009,EV10003,EV10025,EV10020,EV10017,EV10005,EV10000,EV10043,PH10040,PH10013]
Now I would like to go through this list and only return the items that start with 'EV'.
As you tagged startswith, instead of filtering the array afterwards, you could add an extra check if the string starts with EV before pushing the question id to the items array.
For example
if (question.IsInCategory(category) && question.Id.startsWith("EV")) items.push(question.Id);

Remove duplicates in array separated by double commas in JavaScript

I have an array in JavaScript like this
var data = [,A_1_VII,VII,V2,,A_1_VII,VII,V2,,A_1_VII,VII,V2,,B_1_XIV,XIV,V3,,B_2_XVI,XVI,V3]
when I alert in JavaScript it gives as below
,A_1_VII,VII,V2
,A_1_VII,VII,V2
,A_1_VII,VII,V2
,B_1_XIV,XIV,V3
,B_2_XVI,XVI,V3
But I want like this which is duplicates removed array
var unique_data = [,A_1_VII,VII,V2,,B_1_XIV,XIV,V3,,B_2_XVI,XVI,V3]
On alert it should give like this
,A_1_VII,VII,V2
,B_1_XIV,XIV,V3
,B_2_XVI,XVI,V3
First Thing your array contains string as a constant that's not going to work.
Secondly, if all of you value are strings you can do it as follows:
var data =[,"A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"B_1_XIV","XIV","V3",,"B_2_XVI","XVI","V3"];
var uniqueArray = data.filter(function(item, pos) {
return data.indexOf(item) == pos;
})
alert(uniqueArray);
Assuming the variables in your array are well defined, you can clean it up and remove duplicates with a for loop:
var data [/* ... */];
var unique_data = [];
for(let i = 0; i < data.length; i++) {
if (data[i] && unique_data.indexOf(data[i]) === -1) {
unique_data.push(data[i]);
}
}
Please note that the code above assumes that your array contains non-object types, otherwise the solution would need to use something more sophisticated than indexOf().
You can create your unique function to remove duplicate entry and empty value from array like this.
var data =[,"A_1_VII,VII","V2,,A_1_VII","VII","V2",,"A_1_VII","VII","V2",,"B_1_XIV,XIV","V3",,"B_2_XVI,XVI,V3"]
var unique_data = uniqueList(data);
alert(unique_data);
function uniqueList(list) {
var uniqueResult = [];
$.each(list, function(i, e) {
if ($.inArray(e, uniqueResult) == -1 &&$.inArray(e, uniqueResult)!="")// chech for unique value and empty value
uniqueResult.push(e);
});
return uniqueResult ;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Advice on the best way to collect values in an array

I need to save all the color values ​​of the elements in the pages of my site and put them in a database. I thought I'd do it this way:
First thing I'm going to pick up the rgb values ​​of each element so
$("*").each(function(e){
createColorArray($(this).css('backgroundColor'));
});
then in the function createColorArray store into an array all the values ​​that are passed
function createColorArray(rgbColor)
{
//Create rgb array
}
and finally remove duplicate items from my array
function removeDoupe(ar) {
var temp = {};
for (var i = 0; i < ar.length; i++)
temp[ar[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
}
now my question is,
how recommended to create the array? directly inside the $ ("*") or in a dedicated function as I'm thinking? also i need than once removed duplicates in the new array "clean" as well as the rgb value I would have also given the number of times that value was in the original.
Some example code?
As I mentioned in the comments, why not check for duplicates earlier? A simple example:
var colors = [];
$('*').each(function(i, el){
var $element = $(el),
color = $element.css('background-color');
if(!~$.inArray(color, colors))
colors.push(color);
});
console.log(colors);
http://jsfiddle.net/sL9oeywk/
The best way to do this is to do it all while you are working on it. Heres a way you could potentially do it:
var colors = new Array();
var tempColors = {};
$(".colors").each(function(){
var c = $(this).val();
// check if the color exists without looping
if(typeof tempColors[c] == "undefined"){
// if it doesn't, add it to both variables.
tempColors[c] = true;
colors.push(c);
}
});
This will result in two variables: one is an object that you don't have to loop through to find out if you defined it before, one is a colors array that you push to using standard javascript.
You shouldn't make it a dedicated function if you are not reusing it, but you could make it an object like this:
var colors = function(){
var self = this;
self.array = new Array();
// this is a dedicated check function so we don't need separate variables.
// returns true if the color exists, false otherwise
self.check = function(color){
for(var i =0; i < self.array.length; i++){
if(self.array[i] === color) return true;
}
return false;
}
self.add = function(color){
// use the check function, if it returns false, the color does not exist yet.
if(!self.check(color)){
self.array.push(c);
}
}
}
You can then instantiate a colorlist using var colorlist = new colors(); and add colors using colorlist.add("dd0300"). Accessing the array can be done by requesting colorlist.array.

Can I change the way key pair data is stored to make the access very efficient?

I have the following array that contains user data. There are only about 20 elements in thsi data. I get this from my server and it is stored locally:
var userdata1 =
[
{"id":"527ddbd5-14d3-4fb9-a7ae-374e66f635d4","name":"xxx"},
{"id":"e87c05bc-8305-45d0-ba07-3dd24438ba8b","name":"yyy"}
]
I have been using the following function to get the user name from my userProfiles array.
$scope.getUser = function (userId) {
if (userId && $scope.option.userProfiles)
for (var i = 0; i < $scope.option.userProfiles.length; i++)
if ($scope.option.userProfiles[i].id === userId)
return $scope.option.userProfiles[i].name;
return '';
}
I was looking for a more efficient way to get the name so I asked this question:
How can I check an array for the first occurence where a field matches using _lodash?
Now I am wondering. Is there another way that I could store my data to make it easier to access? One person suggested this
in the comments:
var usersdata2 = {someuserid: {id: "someusersid", name: 'Some Name'},
anotheruserid: {id: "anotheruserid", name: 'Another Name'}};
If I was to do this then would it be more efficient, how could I change my data from the first form userdata1 into userdata2
and how could I access it?
You can transform your array as follows:
var userMap = userdata1.reduce(function(rv, v) {
rv[v.id] = v;
return rv;
}, {});
That will give you an object that maps the "id" values onto the original object. You would then access the values like this:
var someUser = userMap[ someUserId ];
This set up will be much more efficient than your array, because finding an entry takes an amount of time proportional to the size of the "id" strings themselves (plus a little). In your version, you have to search through (on average) half the list for each lookup. For a small set of records, the difference would be unimportant, but if you've got hundreds or thousands of them the difference will be huge.
The .reduce() function is not available in older browsers, but there's a fill-in patch available on the MDN documentation site:
// copied from MDN
if ('function' !== typeof Array.prototype.reduce) {
Array.prototype.reduce = function(callback, opt_initialValue){
'use strict';
if (null === this || 'undefined' === typeof this) {
// At the moment all modern browsers, that support strict mode, have
// native implementation of Array.prototype.reduce. For instance, IE8
// does not support strict mode, so this check is actually useless.
throw new TypeError(
'Array.prototype.reduce called on null or undefined');
}
if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function');
}
var index, value,
length = this.length >>> 0,
isValueSet = false;
if (1 < arguments.length) {
value = opt_initialValue;
isValueSet = true;
}
for (index = 0; length > index; ++index) {
if (this.hasOwnProperty(index)) {
if (isValueSet) {
value = callback(value, this[index], index, this);
}
else {
value = this[index];
isValueSet = true;
}
}
}
if (!isValueSet) {
throw new TypeError('Reduce of empty array with no initial value');
}
return value;
};
}
Try something like this:
var usernames = {};
userdata1.forEach(function(u) {usernames[u.id] = u.name;});
alert(usernames[userId]);
(You'll either need a shim or a manual for loop to support older browsers - the above is intended to just give you an idea on how you can simplify your access)
To make the access by ID more efficient copy the data into an object:
var userdata1 =
[
{"id":"527ddbd5-14d3-4fb9-a7ae-374e66f635d4","name":"xxx"},
{"id":"e87c05bc-8305-45d0-ba07-3dd24438ba8b","name":"yyy"}
];
var userIdMap = {};
for (var i = 0; i < userdata1.length; i++) {
var item = userdata1[i];
userIdMap[item.id] = item;
}
which means the function is now:
$scope.getUser = function (userId) {
if (userId && $scope.option.userProfiles) {
var user = userIdMap[userId];
if(user)
return user.name;
}
return '';
}
Here is a function that puts your array items into a lookup object:
function arrayToLookup(array, idProperty) {
var result = {};
for (var i = array.length - 1; i >= 0; i--) {
result[array[i][idProperty]] = array[i];
}
return result;
}
Usage would be like this, for your example:
var userdata1 =
[
{"id":"527ddbd5-14d3-4fb9-a7ae-374e66f635d4","name":"xxx"},
{"id":"e87c05bc-8305-45d0-ba07-3dd24438ba8b","name":"yyy"}
]
// create a lookup object of your array.
// second parameter is the name of the property to use as the keys
var userDataLookup = arrayToLookup(userdata1, 'id');
// this is how you get a specific user out of the lookup
var user = userDataLookup["527ddbd5-14d3-4fb9-a7ae-374e66f635d4"];

jquery split() issue

Hopefully this is easy for someone.
I have a set of checkboxes with values 1,2,3 etc with the same name attribute (cp_bundle).
I use the following code to get a comma-delimited list of those checkboxes.
var hl_calling_plan_bundle = $('input[name="cp_bundle"]:checked').getCheckboxVal() || "";
jQuery.fn.getCheckboxVal = function(){
var vals = [];
var i = 0;
this.each(function(){
vals[i++] = jQuery(this).val();
});
return vals;
}
if I check the first and third checkboxes, the following will be returned:
1,3
Then, I want to run a test to see whether a particular value (e.g. "3") exists in the the returned variable
But, I can't get past the split of the variable using the following:
var aCallingBundle = hl_calling_plan_bundle.split(",");
This gives the error:
hl_calling_plan_bundle.split is not a function
Any idea what's going on?
hl_calling_plan_bundle is an array. You have to use array operations on it, not string operations.
If you want to know if the value 3 is in the array, then you have to search the array for it. There are many ways to search an array, but since you have jQuery, it's easy to use the .inArray() function:
var index = $.inArray(3, hl_calling_plan_bundle);
if (index != 1) {
// found 3 in the array at index
}
Incidentally, you may want to simplify your function like this:
jQuery.fn.getCheckboxVal = function(){
var vals = [];
this.each(function(){
vals.push(this.value);
});
return vals;
}
or this way:
jQuery.fn.getCheckboxVal = function(){
return(this.map(function(){return(this.value)}).get());
}
split() is a String method, it does not exist on an Array.
When you say the following is returned 1,3, you may be implicitly calling the String's toString() method, which will by default join() the array members with a comma. If you explicitly called toString(), then you could call split(), but that would be an anti pattern.
You don't need to split the string, you can just use RegEx to search:
var str = '1,3,22,5';
/\b1\b/.test(str); // true
/\b2\b/.test(str); // false
/\b3\b/.test(str); // true
/\b5\b/.test(str); // true
/\b22\b/.test(str); // true
Making it a function:
String.prototype.findVal = function(val){
var re = new RegExp('\\b' + val + '\\b');
re.lastIndex = 0;
return re.test(this);
};
str.findVal(2); // false
str.findVal(22); // true
To get the checkboxes:
var cbs = document.getElementsByName('cp_bundle');
To get arrays of all values and the checked values:
var allValues = [];
var checkedValues = [];
for (var i=0, iLen=cbs.length; i<iLen; i++) {
if (cbs[i].checked) checkedValues.push(cbs[i].value);
allValues[i] = cbs[i].value;
}

Categories