I have an array with Strings, if there is nothing written in the String I want to remove it from the array with .splice().
Somehow it does not get all empty entries. If there are 2 empty entries in the beginning, it only gets one.
Here is my fiddle and code:
stringArray = ["", "", "Banana"];
console.log('before stringArray.length: ' + stringArray.length);
for (var i = 0; i < stringArray.length; i++) {
if (stringArray[i] === "") {
stringArray.splice(i, 1);
if (i > 0) i--;
}
}
console.log('after stringArray.length: ' + stringArray.length);
You have to loop backwards, because every time you splice, the length and indexes change:
for (var i = stringArray.length-1; i>=0; i--) {
if(stringArray[i] === ""){
stringArray.splice(i, 1);
}
}
Alternate solution with Array.prototype.filter (documentation page provides a shim for old browsers that won't support this method):
stringArray = [ "","","Banana"];
var a = stringArray.filter(function(item) {
return item !== '';
});
console.log(a);
Another option, of course with looping backwards, is with a while loop:
var stringArray = ["", "", "", "Apple", "", "", "Banana", "", "", ""];
var i = stringArray.length;
while (i-- && (stringArray[i] !== "" || stringArray.splice(i, 1)));
console.log(stringArray); // ["Apple", "Banana"]
DEMO: http://jsfiddle.net/VEmAV/
Related
I have an array like below let's say
var myArray = ["1", "", "", "2","3","","","8"];
And I want to fill each " " value with previous not null value
According to that expectation should be like below
var myArray = ["1", "2", "2", "2","3","8","8","8"];
Here what I tried but didn't work
var myArray = ["1", "", "", "2","3","","","8"];
function myFunction() {
let currentEl=myArray [0];
let prevIndex=0;
fruits.map((e,a)=>{
if(e!="" && myArray[a-1]==""){
currentEl=e;
let interval=arrayGenerate(a-currentIndex-1,currentEl);
fruits.splice(currentIndex-1, currentEl+1, interval);
currentIndex=a;
}
})
}
function arrayGenerate(iteration,value){
let arr=[];
for(var i=0;i<iteration;i++){
arr.push(value);
}
return arr;
}
console.log(myArray)
You could map the new values and find the missing following value.
var array = ["1", "", "", "2", "3", "", "", "8"],
result = array.map((v, i, a) => v || a.find((w, j) => j > i && w));
console.log(result);
A solution with the same array, by looping from the end and storing the last value.
var array = ["1", "", "", "2", "3", "", "", "8"],
i = array.length,
value;
while (i--) {
if (array[i]) value = array[i];
else array[i] = value;
}
console.log(array);
I have done it like this. I loop over and awlays check the next element if its falsy and not the last element.
var myArray = ["1", "", "", "2","3","","","8"];
function fillArr(arr){
for(let i = arr.length - 1; i >= 0; i--){
if(!arr[i - 1] && i != arr.length){
arr[i - 1] = arr[i];
}
}
return arr;
}
let result = fillArr(myArray);
console.log(result);
You can make use of a stack array to stack indices of null items and then unstack them whenever you encounter a non null item in myArray. (stack is not a reserved keyword so you can call it anything) :
var stack = []
for(var i = 0; i < myArray.length; i++){
if(myArray[i] === "")
stack.push(i);
else if(stack.length !== 0){
for(var j = stack.length - 1 ; j > =0; j--){
myArray[stack[j]] = myArray[i];
stack.splice(j,1);
}
}
}
It's interesting how many different ways this can be done. Just another slightly ugly way to do the same thing:
const fill = (arr, lastVal) => (
arr.reverse()
.map(el => el.length > 0 ? lastVal = el : lastVal)
.reverse()
);
console.log(fill(["1", "", "", "2","3","","","8"]));
Say I have an array of objects like so:
[{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
I need to count the occurrence of each element and return in it in an array
[3, 0, 1, 2]
any ideas would be appreciated, thanks!
I have attempted
var a = datasets.reduce(function (item, index) {
if (typeof item[index] == 'undefined') {
item[index] = 1;
} else {
item[index] += 1;
}
return item;
}, {});
could not get anything like that to work so i attempted converting it to json and then removing any key: value pairs with no value then counting remaining ones but have had no success with that either
function tableToJson(table) {
var data = [];
var headers = [];
for (var i=0; i < table[0].rows[0].cells.length; i++) {
headers[i] = table[0].rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
}
for (var i=1; i< table[0].rows.length; i++) {
var tableRow = table[0].rows[i];
var rowData = {};
for (var j=0; j<tableRow.cells.length; j++) {
rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
return data
}
function removeEmpty(jsonObj) {
var newObj = Object.getOwnPropertyNames(jsonObj);
for (var i = 0; i < newObj.length; i++) {
var value = newObj[i];
if (jsonObj[value] === null || jsonObj[value] === undefined) {
delete jsonObj[value];
}
}
}
You can try this
You can do it with reduce().
What i have done is first i check is the object property of current element if it is already in output object. If it's present than i check the value of current element property. if it is true than i increment the property of output object by 1.
If the object property of current element is not available in output than i check for the value of current element property. if it is true i assign output object property with value 1. if false i assign output object property with 0.
let obj = [{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
let op = obj.reduce((output,current)=>{
for(let key in current){
if( output[key] ){
if( current[key] ) output[key]+=1;
} else {
if( current[key] ){
output[key] = 1;
} else{
output[key] = 0;
}
}
}
return output;
},{})
console.log(op);
Try this:
var data = [{
taco: "",
burrito: "",
scone: "",
beans: "true"
},
{
taco: "true",
burrito: "",
scone: "true",
beans: ""
},
{
taco: "",
burrito, "true",
scone: "",
beans: "",
}, {
taco: "true",
burrito: "",
scone: "",
beans: "true"
}]
var total = [0, 0, 0, 0];
data.forEach(function(obj) {
if (obj.taco) {
total[0]++;
}
if (burrito) {
total[1]++;
}
if (obj.scone) {
total[2]++;
}
if (obj.beans) {
total[3]++;
}
})
console.log(total)
You can loop through the array and then loop through the keys of each object. Then increment the key of the countObject if it already exists or assign it zero.
This is dynamic. Even if one of the object has an extra key, it will count them. This doesn't expect all the items of array to have the same keys.
var array = [
{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}
]
var countObject = {};
array.forEach(item => {
Object.keys(item).forEach(key => {
if (item[key] === "true")
countObject[key] = countObject[key] + 1 || 1
else
countObject[key] = countObject[key] || 0
})
})
console.log(countObject); // get the key and count pair
console.log(Object.values(countObject)); // get the counts in an array
I come up with this solution to compare a string to an array of object. However, I don't think this is the best solution. Any suggestion on how to make this function perform better for large array of object?
var a = "blAh";
var b = [{
"tag": "tag1",
"icons": ["blah"]
}, {
"tag": "tag2",
"icons": ["Blah", "apple", "banana", "bLaH"]
}];
// Desired output "tag1, tag2"
function getTitle(tags, icon) {
let arr = [];
for (var i = 0; i < tags.length; i++) {
tags[i].icons.forEach(elem => {
if (icon.toLowerCase() === elem.toLowerCase()) {
if (!arr.includes(tags[i].tag)) {
arr.push(tags[i].tag);
}
}
});
}
return arr.join(', ');
}
console.log(getTitle(b, a));
for readability, I would use the following :
var res = b.filter(el =>
el.icons.length < 0
? false
: el.icons.map(icon => icon.toLowerCase()).indexOf(a.toLocaleLowerCase()) != -1
).map(el => el.tag).join(', ');
But for performances, this one would be better :
var res = [];
var i, j;
for (i = 0; i < b.length; i++) {
if (b[i].icons.length < 0) {
} else {
for (j = 0; j < b[i].icons.length; j++)
b[i].icons[j] = b[i].icons[j].toLowerCase();
if (b[i].icons.indexOf(a.toLocaleLowerCase()) !== -1)
res.push(b[i].tag);
}
}
res = res.join(', ');
Here is why :
indexOf is always faster than includes (or equal in old versions of chrome). benchmark
for loops are always faster than array methods like filter, map or reduce. benchmarks : map, filter
Also it's intresting to see that for loops are faster than indexOf in the latest version of chrome (60)
Hope it helps,
Best regards
I have the following code.
function findMatch(array_1_small, array2_large) {
var ary = new Array();
for(i = 0;i < array2_large.length; i++)
{
for(z = 0; z < array_1_small.length; z++)
{
if(array2_large[i] == array_1_small[z])
{
var idx = array2_large.indexOf(array2_large[i]);
ary.push(idx);
}
}
}
return ary;
}
That takes the following arrays.
var all_SMS_TO = ["0861932936", "0871355066", "0874132026", "0872908445", "0874132026"];
var all_FORM_NUMBERS = ["", "", "", "", "", "", "0871355066",""];
The sole purpose is to find a match and return the index of the match on the 'all_form_numbers array.
On calling the code
var a = findMatch(all_SMS_TO, all_FORM_NUMBERS);
console.log("Match Found " + a);
I get the following output.
Match Found: 6
Which is correct, however when I alter the all_form_Numbers array to
var all_FORM_NUMBERS = ["", "0871355066", "", "", "", "", "0871355066",""];
I get The following output.
Match Found: 1,1
Could somebody help me with this so it should output;
Match Found 1, 6.
Thanks.
try this:
function findMatch(array_1_small, array2_large) {
var ary = new Array();
for(i = 0;i < array2_large.length; i++)
{
for(z = 0; z < array_1_small.length; z++)
{
if(array2_large[i] == array_1_small[z])
{
ary.push(i);
}
}
}
return ary;
}
When you do
var idx = array2_large.indexOf(array2_large[i]);
you are searching for the index of the value 0871355066 in the array array2_large twice and as per the definition of indexOf it will returns the position of the first occurrence of a specified value.
This is why you are getting index value 1 twice since its the index of first occurrence.
For solution Just push the variable i value into the array ary. Which is already the index value of array2_large in the loop.
function findMatch(array_1_small, array2_large) {
var ary = new Array();
for(i = 0;i < array2_large.length; i++)
{
for(z = 0; z < array_1_small.length; z++)
{
if(array2_large[i] == array_1_small[z])
{
ary.push(i);
}
}
}
return ary;
}
var all_SMS_TO = ["0861932936", "0871355066", "0874132026", "0872908445", "0874132026"];
//var all_FORM_NUMBERS = ["", "", "", "", "", "", "0871355066",""];
var all_FORM_NUMBERS = ["", "0871355066", "", "", "", "", "0871355066",""];
var a = findMatch(all_SMS_TO, all_FORM_NUMBERS);
console.log("Match Found " + a);
You just need to push the index i here is the fixed code (you can also declare an array as var res = [];
function findMatch(arraySmall, arrayLarge) {
var res = []
for (var i = 0; i < arrayLarge.length; i++) {
for (var j = 0; j < arraySmall.length; j++) {
if (arrayLarge[i] === arraySmall[j]) {
res.push(i);
}
}
}
return res;
}
It is possible to solve this on O(n+m) runtime complexity by creating a lookup table of positions first. Then you map each element from the first array to all positions and collect these indices in a Set to only leave unique values.
Try this:
var all_SMS_TO = ["0861932936", "0871355066", "0874132026", "0872908445", "0874132026"];
var all_FORM_NUMBERS = ["", "0871355066", "", "", "", "", "0871355066",""];
function findMatch(array_1_small, array2_large) {
var positions = Array.from(array2_large.entries()).reduce((acc, t) => {
var index = t[0]
var element = t[1]
if (!acc.hasOwnProperty(element)) {
acc[element] = []
}
acc[element].push(index)
return acc
}, {})
var result = new Set()
array_1_small.forEach(x => {
if (positions[x] === undefined) {
return
}
positions[x].forEach(index => result.add(index))
})
return Array.from(result)
}
console.log("Match found: " + findMatch(all_SMS_TO, all_FORM_NUMBERS))
I have two arrays, and I'm comparing two values, and then setting a json object:
var compare = ["hh", "pictures", "videos", "aboutMe", "contactMe", "cat", "location"];
var data = ["pictures", "videos", "aboutMe", "contactMe", "cat", "location"];
for (var j=0; j<compare.length; j++) {
if (compare[j] === data[j]) {
self.MenuItems.menu_item[j].added = "added";
}else if (compare[j] !== data[j]){
self.MenuItems.menu_item[j].added = "";
}
}
for some reason, for all self.MenuItems.menu_item[j], they all equal either "added" or "";...
Just so you know this condition is not very efficient, here how it should be
if (compare[j] === data[j]) {
self.MenuItems.menu_item[j].added = "added";
}else {
self.MenuItems.menu_item[j].added = "";
}
and the code does what is intended. Unless you had something else in mind.