Related
Write a function that takes in a list and returns a list with all of the duplicates removed (list will only have unique numbers).
Here's what I have so far:
var lista = [1,4,5,1,1,3,5,6,4,4,3];
function dupRemove (lista) {
//Sort the array in case it isn't sorted
lista.sort();
//Object to store duplicates and unique numbers
var listNumbers = {
"Duplicate Numbers": [],
"Unique Numbers": []
};
for (var i = 0; i < lista.length; i++) {
//check if it is not equal to the index of the array before it and after. if it isn't, that means its unique, push it in the uniques array.
if (lista[i] !== lista[i-1] && lista[i] !== lista[i+1]) {
listNumbers["Unique Numbers"].push(lista[i]);
} else {
listNumbers["Duplicate Numbers"].push(lista[i]);
}
}
return listNumbers;
}
Currently, my solution returns an object with keys with the values of "Duplicates": 1, 1, 1, 3, 3, 4, 4, 4, 5, 5 and "Uniques": 6.
How do I remove the duplicates from duplicates and then join these two keys into a single array?
Thank you.
that answer is seriously over -engineered- all you need to to is push all values into a new array if they are not already in it.
function=removeDups()
{
var lista = [1,4,5,1,1,3,5,6,4,4,3];
var uniqueValues=[];
var duplicateValues=[];
for(i=0;i<lista.length;i++)
{
if(uniqueValues.indexof(lista[i] == -1){uniqueValues.push(lista[i]}else{duplicateValues.push(lista[i]}
}
}
You could just use the default filter method that is on all Arrays
You don't need the sort function either. If the item is already found using the indexOf method it will not be added to the newly returned array created by the filter method
var list = [1,4,5,1,1,3,5,6,4,4,3];
function removeDup (arr) {
return arr.filter(function(item, pos) {
return arr.indexOf(item) == pos;
})
}
var sortedList = removeDup(list).sort(function(a,b){
return a - b
})
document.getElementsByTagName('div')[0].textContent = sortedList
<div></div>
Kind of a non elegant solution but it gives you the two arrays: one with the duplicate values and one with the unique ones. Since you cannot rely on .sort() you can just count things.
Function checkList will give you back those two arrays.
var list = [1,4,5,1,1,3,5,6,4,4,3];
console.log(checkList(list));
function checkList(list) {
var uniques = []; // will be [6]
var dups = []; // will be [1, 4, 5, 3]
var checked = []; // save what you have already checked so far
for(i = 0; i < list.length; i++) {
if(notChecked(list[i], checked)) {
checked.push(list[i]);
if(count(list[i], list) > 1) {
dups.push(list[i]);
} else {
uniques.push(list[i]);
}
}
}
return {dups: dups, uniques: uniques}
}
// count how many num in arr
function count(num, arr) {
var count = 0;
var i;
for(i = 0; i < arr.length; i++) {
if(arr[i] == num) count++;
if(count > 1) return count;
}
return count;
}
// check if num has not been checked
function notChecked(num, arr) {
return (arr.indexOf(num) == -1) ? true : false;
}
I've created this codepen http://codepen.io/PiotrBerebecki/pen/ZWxvzm when trying to find an array containing symmetric difference of two or more arrays.
My function works OK but only if four arguments are passed. How can I modify my function so that it can accept an unknown number of arguments? There is a potentially repeatable block of code that perhaps could be part of a for loop or reduce / map methods. I can't figure out how to accomplish this.
symmetricDifference([1,2,3,4], [3,4,5,6], [2,4,6,7], [8,9])
// should return an array containing [1,4,5,7,8,9]
symmetricDifference([1,2,3,4], [3,4,5,6])
// should return an array containing [1,2,5,6]
var arrA = [1,2,3,4];
var arrB = [3,4,5,6];
var arrC = [2,4,6,7];
var arrD = [8,9];
function symmetricDifference(arr) {
let args = Array.prototype.slice.call(arguments);
let result = [];
result = args[0].concat(args[1]).filter(function(item) {
return args[0].indexOf(item) === -1 || args[1].indexOf(item) === -1;
});
result = result.concat(args[2]).filter(function(item) {
return result.indexOf(item) === -1 || args[2].indexOf(item) === -1;
});
result = result.concat(args[3]).filter(function(item) {
return result.indexOf(item) === -1 || args[3].indexOf(item) === -1;
});
return result;
}
Thanks to the hints by #Bergi I've introduced a for loop and an initial value var result = args[0]; The function is working now as desired as it accepts an unknown number of arguments. I've updated the original codepen (http://codepen.io/PiotrBerebecki/pen/ZWxvzm) to demonstrate this implementation.
function symmetricDifference(arr) {
let args = Array.prototype.slice.call(arguments);
let result = args[0];
for (var i = 1; i < args.length; i++) {
result = result.concat(args[i]).filter(function(item) {
return result.indexOf(item) === -1 || args[i].indexOf(item) === -1;
});
}
// remove duplicates and sort
return Array.from(new Set(result)).sort((a, b) => a - b);
}
I have two multidimensional array and i want to create a third multidimensional array:
var reports = [
[48.98,153.48],
[12.3,-61.64]
];
var vulc = [
["ciccio",48.98,153.48],
["cicci",12.3,-61.64],
["intruso",59.9,99.9]
];
And i want to create a new multidimensional array
var nuovarray= [];
for (i=0; i<= reports.length; i++) {
var attivi= reports[i];
var attlat= attivi[0];
var attlng= attivi[1];
for (s=0; s<=vulc.length; s++){
var vulca= vulc[s];
var vulcanam= vulca[0];
var vulcalat= vulca[1];
var vulcalng= vulca[2];
if ((vulcalat==attlat) && (vulcalng==attlng){
var stato= "A";
nuovarray.push([vulcanam,vulcalat,vulcalng,stato]);
}
else{
var stato= "N";
nuovaarray.push([vulcanam,vulcalat,vulcalng,stato]);
}
}
}
i would like to have
var nuovarray= [
["ciccio",48.98,153.48,"N"],
["cicci",12.3,-61.64,"N"],
["intruso",59.9,99.9,"A"]
];
But i don't know if this code is good :/
As I said in the comment, in the for loop, use < not <= (array of length N has indexes 0 ... N-1) ... and swap the outer loop with the inner loop, and only push with value 'N' before the end of the outer loop if the inner loop hasn't pushed with value 'A'
var reports = [
[48.98,153.48],
[12.3,-61.64]
];
var vulc = [
["ciccio",48.98,153.48],
["cicci",12.3,-61.64],
["intruso",59.9,99.9]
];
var nuovarray= [];
for(var s = 0; s < vulc.length; s++) {
var vulca = vulc[s];
var stato= "A"; // default, no match
var vulcanam= vulca[0];
var vulcalat= vulca[1];
var vulcalng= vulca[2];
for(var i = 0; i < reports.length; i++) {
var attivi = reports[i];
var attlat= attivi[0];
var attlng= attivi[1];
if ((vulcalat==attlat) && (vulcalng==attlng)) {
stato = "N";
break; // we've found a match, so set stato = N and stop looping
}
}
nuovarray.push([vulcanam,vulcalat,vulcalng,stato]);
}
document.getElementById('result').innerHTML = (nuovarray).toSource();
<div id='result'></div>
I believe the code will not work the way it is written. At least, it will not give you the expected output. You are iterating through the vulc array inside the loop which iterates through reports. And you are pushing to the nuovarray inside the inner loop. So I would expect 6 elements in nuovarray, not the 3 elements you are expecting.
Did you try running it? That's the easiest way to prove incorrectness.
var reports = [
[48.98,153.48],
[12.3,-61.64]
];
var vulc = [
["ciccio",48.98,153.48],
["cicci",12.3,-61.64],
["intruso",59.9,99.9]
];
var nuovarray = [];
vulc.forEach(function(item, indx){
var bN = 'undefined' !== typeof reports[indx];
bN = bN && item[1] == reports[indx][0] && item[2] == reports[indx][1];
item.push(bN ? 'N' : 'A');
nuovarray.push(item);
});
console.log(nuovarray);
The code maps the given vulc to nuovarray and add the wanted flag to it. The flag is selected by a search over reports and if found, an 'N' is applied, otherwise an 'A' is applied.
var reports = [
[48.98, 153.48],
[12.3, -61.64]
],
vulc = [
["ciccio", 48.98, 153.48],
["cicci", 12.3, -61.64],
["intruso", 59.9, 99.9]
],
nuovarray = vulc.map(function (a) {
a.push(reports.some(function (b) {
return a[1] === b[0] && a[2] === b[1];
}) ? 'N' : 'A')
return a;
});
document.getElementById('out').innerHTML = JSON.stringify(nuovarray, null, 4);
<pre id="out"></pre>
The map() method creates a new array with the results of calling a provided function on every element in this array.
Array.prototype.map()
The push() method adds one or more elements to the end of an array and returns the new length of the array.
Array.prototype.push()
The some() method tests whether some element in the array passes the test implemented by the provided function.
Array.prototype.some()
var reports = [
[48.98,153.48],
[12.3,-61.64]
];
var vulc = [
["ciccio",48.98,153.48],
["cicci",12.3,-61.64],
["intruso",59.9,99.9]
];
console.log(vulc.map(function (item, index) {
item.push(reports.some(function (report) {
return report[0] == item[1] && report[1] == item[2];
})?"N":"A");
return item;
}));
If performance matters, you should use something better than O(n^2):
var existingPoints = {};
reports.forEach(function (row) {
existingPoints[row.join()] = true;
});
var nuovarray = vulc.map(function (row) {
var point = row.slice(1, 3).join();
var flag = existingPoints[point] ? 'A' : 'N';
return row.concat([flag]);
});
Is there an easy way of knowing if and array contains all elements of another array?
Example:
var myarray = [1,2,3];
var searchinarray = [1,2,3,4,5];
searchinarray contains all elements of myarray, so this should return true.
Regards
Here is an implementation of that function:
function contains(a, s) {
for(var i = 0, l = s.length; i < l; i++) {
if(!~a.indexOf(s[i])) {
return false;
}
}
return true;
}
This shows that it does what you describe:
> var myarray = [1,2,3];
> var searchinarray = [1,2,3,4,5];
> contains(myarray, searchinarray)
false
> contains(myarray, [1,2])
true
> contains(myarray, [2,3])
true
A contains function should only visit members of the array to be contained that exist, e.g.
var myArray = [1,,2];
var searchInArray = [1,2,3];
contains(myArray, searchInArray);
should return true, however a simple looping solution will return false as myArray[1] doesn't exist so will return undefined, which is not present in the searchInArray. To easily avoid that and not use a hasOwnProperty test, you can use the Array every method:
function contains(searchIn, array) {
return array.every(function(v){return this.indexOf(v) != -1}, searchIn);
}
so that:
var a = [1,,3];
var s = [1,2,3,4,5];
console.log(contains(s, a)); // true
You can add a contains method to all instances of Array if you wish:
if (typeof Array.prototype.contains == 'undefined') {
Array.prototype.contains = function(a) {
return a.every(function(v, i) {
return this.indexOf(v) != -1;
}, this);
}
}
console.log(s.contains(a)); // true
console.log(s.contains([1,9])); // false
You may need a polyfill for browsers that don't have .every (IE 8?).
function compare(array, contains_array) {
for(var i = 0; i < array.length; i++) {
if(contains_array.indexOf(array[i]) == -1) return false;
}
return true;
}
compare(myarray, searchinarray);
var arr = [["test","1"],["demo","2"]];
// $.inArray() ???
// .splice() ???
// $.each() ???
$("code").html(JSON.stringify(arr));
If I will find matching array by "test" (unique) keyword , I will remove ["test","1"]
So arr after removed will be [["demo","2"]]
How can I do that ?
Playground : http://jsbin.com/ojoxuy/1/edit
This is what filter is for:
newArr = arr.filter(function(item) { return item[0] != "test" })
if you want to modify an existing array instead of creating a new one, just assign it back:
arr = arr.filter(function(item) { return item[0] != "test" })
Modificator methods like splice make code harder to read and debug.
You could do something like this:
function remove(oldArray, itemName) {
var new_array = [];
for(var i = 0, len = oldArray.length; i < len; i++) {
var arr = oldArray[i];
if (arr[0] != itemName) new_array.push(arr);
}
return new_array;
}
And call it like this:
var arr = [["test","1"],["demo","2"]];
var new_arr = remove(arr,'test');
I'm making assumptions here and not doing any real error checking but you get the idea.
Perhaps something like:
for(var i = 0; i < arr.length; i++) {
if(arr[i][0] == "test") {
arr.splice(i, 1);
break;
}
}
var arr = [["test","1"],["demo","2"]];
function checkArrayElements(a, index, arr) {
if(a[0]=="test"){
delete arr[index];
arr.splice(index,index+1);
}
}
arr.forEach(checkArrayElements);
$("code").html(JSON.stringify(arr));
NOTE: This removes any inner array in arr with the 0 element = "test"
Check this one
function rmEl(a,v)
{
for(var i=0;i<a.length;i++)
{
if(a[i][0]==v)
{
a.splice(i,i+1);
i=-1;
}
$("code").html(JSON.stringify(a));
}
return a;
}