I am given a string and an array of single character strings as an argument. I need to return the shortest substring that can be found in the given string that contains every character in the array.
I am assuming that all characters are lower case and that the substring will be at least two characters long.
This is how I have it set up:
const solve = (strArg, charArray) => {
let result = '';
const strArray = strArg.split('');
return;
}
solve("environmental earth science", ["n","e","i","m"]);
I want to loop over the strArg and say does this letter exist in the charArray, but I want to use an ES6 array helper method and I have looked at filter(), but if I look at how T.J Crowder defines the use of filter(), that is more for creating a new array.
So then I have also looked at the for..of loop, but I am unclear as to whether I am applying it wrong or the for..of is not the best for the job. I need to iterate over each character in strArray and see if it exists in charArray.
A brute-force solution would be to start at each index of the input string, then increment indicies until all required characters have been found. Do this starting at index 0, then at index 1, etc.
const solve = (str, charArray) => {
let bestStr = str;
for (let i = 0; i < str.length; i++) {
const chars = new Set(charArray);
for (let j = i; j < str.length; j++) {
chars.delete(str[j]);
const thisLen = j - i + 1;
if (chars.size === 0 && bestStr.length > thisLen) {
bestStr = str.slice(i, j + 1);
break;
}
}
}
return bestStr;
}
console.log(solve("environmental earth science", ["n","e","i","m"]));
I don't think filter is very useful here, because constructing an intermediate array doesn't lead to accomplishing anything useful as far as I can see. for..of, while it looks cleaner, doesn't keep track of indicies as well as a plain for loop.
I want to remove an element in an array with multiple occurrences with a function.
var array=["hello","hello","world",1,"world"];
function removeItem(item){
for(i in array){
if(array[i]==item) array.splice(i,1);
}
}
removeItem("world");
//Return hello,hello,1
removeItem("hello");
//Return hello,world,1,world
This loop doesn't remove the element when it repeats twice in sequence, only removes one of them.
Why?
You have a built in function called filter that filters an array based on a predicate (a condition).
It doesn't alter the original array but returns a new filtered one.
var array=["hello","hello","world",1,"world"];
var filtered = array.filter(function(element) {
return element !== "hello";
}); // filtered contains no occurrences of hello
You can extract it to a function:
function without(array, what){
return array.filter(function(element){
return element !== what;
});
}
However, the original filter seems expressive enough.
Here is a link to its documentation
Your original function has a few issues:
It iterates the array using a for... in loop which has no guarantee on the iteration order. Also, don't use it to iterate through arrays - prefer a normal for... loop or a .forEach
You're iterating an array with an off-by-one error so you're skipping on the next item since you're both removing the element and progressing the array.
That is because the for-loop goes to the next item after the occurrence is deleted, thereby skipping the item directly after that one.
For example, lets assume item1 needs to be deleted in this array (note that <- is the index of the loop):
item1 (<-), item2, item3
after deleting:
item2 (<-), item3
and after index is updated (as the loop was finished)
item2, item3 (<-)
So you can see item2 is skipped and thus not checked!
Therefore you'd need to compensate for this by manually reducing the index by 1, as shown here:
function removeItem(item){
for(var i = 0; i < array.length; i++){
if(array[i]==item) {
array.splice(i,1);
i--; // Prevent skipping an item
}
}
}
Instead of using this for-loop, you can use more 'modern' methods to filter out unwanted items as shown in the other answer by Benjamin.
None of these answers are very optimal. The accepted answer with the filter will result in a new instance of an array. The answer with the second most votes, the for loop that takes a step back on every splice, is unnecessarily complex.
If you want to do the for loop loop approach, just count backward down to 0.
for (var i = array.length - 0; i >= 0; i--) {
if (array[i] === item) {
array.splice(i, 1);
}
}
However, I've used a surprisingly fast method with a while loop and indexOf:
var itemIndex = 0;
while ((itemIndex = valuesArray.indexOf(findItem, itemIndex)) > -1) {
valuesArray.splice(itemIndex, 1);
}
What makes this method not repetitive is that after the any removal, the next search will start at the index of the next element after the removed item. That's because you can pass a starting index into indexOf as the second parameter.
In a jsPerf test case comparing the two above methods and the accepted filter method, the indexOf routinely finished first on Firefox and Chrome, and was second on IE. The filter method was always slower by a wide margin.
Conclusion: Either reverse for loop are a while with indexOf are currently the best methods I can find to remove multiple instances of the same element from an array. Using filter creates a new array and is slower so I would avoid that.
You can use loadash or underscore js in this case
if arr is an array you can remove duplicates by:
var arr = [2,3,4,4,5,5];
arr = _.uniq(arr);
Try to run your code "manually" -
The "hello" are following each other. you remove the first, your array shrinks in one item, and now the index you have follow the next item.
removing "hello""
Start Loop. i=0, array=["hello","hello","world",1,"world"] i is pointing to "hello"
remove first item, i=0 array=["hello","world",1,"world"]
next loop, i=1, array=["hello","world",1,"world"]. second "hello" will not be removed.
Lets look at "world" =
i=2, is pointing to "world" (remove). on next loop the array is:
["hello","hello",1,"world"] and i=3. here went the second "world".
what do you wish to happen? do you want to remove all instances of the item? or only the first one? for first case, the remove should be in
while (array[i] == item) array.splice(i,1);
for second case - return as soon as you had removed item.
Create a set given an array, the original array is unmodified
Demo on Fiddle
var array=["hello","hello","world",1,"world"];
function removeDups(items) {
var i,
setObj = {},
setArray = [];
for (i = 0; i < items.length; i += 1) {
if (!setObj.hasOwnProperty(items[i])) {
setArray.push(items[i]);
setObj[items[i]] = true;
}
}
return setArray;
}
console.log(removeDups(array)); // ["hello", "world", 1]
I must say that my approach does not make use of splice feature and you need another array for this solution as well.
First of all, I guess your way of looping an array is not the right. You are using for in loops which are for objects, not arrays. You'd better use $.each in case you are using jQuery or Array.prototype.forEach if you are using vanila Javascript.
Second, why not creating a new empty array, looping through it and adding only the unique elements to the new array, like this:
FIRST APPROACH (jQuery):
var newArray = [];
$.each(array, function(i, element) {
if ($.inArray(element, newArray) === -1) {
newArray.push(region);
}
});
SECOND APPROACH (Vanila Javascript):
var newArray = [];
array.forEach(function(i, element) {
if (newArray.indexOf(element) === -1) {
newArray.push(region);
}
});
I needed a slight variation of this, the ability to remove 'n' occurrences of an item from an array, so I modified #Veger's answer as:
function removeArrayItemNTimes(arr,toRemove,times){
times = times || 10;
for(var i = 0; i < arr.length; i++){
if(arr[i]==toRemove) {
arr.splice(i,1);
i--; // Prevent skipping an item
times--;
if (times<=0) break;
}
}
return arr;
}
An alternate approach would be to sort the array and then playing around with the indexes of the values.
function(arr) {
var sortedArray = arr.sort();
//In case of numbers, you can use arr.sort(function(a,b) {return a - b;})
for (var i = 0; sortedArray.length; i++) {
if (sortedArray.indexOf(sortedArray[i]) === sortedArray.lastIndexOf(sortedArray[i]))
continue;
else
sortedArray.splice(sortedArray.indexOf(sortedArray[i]), (sortedArray.lastIndexOf(sortedArray[i]) - sortedArray.indexOf(sortedArray[i])));
}
}
You can use the following piece of code to remove multiple occurrences of value val in array arr.
while(arr.indexOf(val)!=-1){
arr.splice(arr.indexOf(val), 1);
}
I thinks this code much simpler to understand and no need to pass manually each element that what we want to remove
ES6 syntax makes our life so simpler, try it out
const removeOccurences = (array)=>{
const newArray= array.filter((e, i ,ar) => !(array.filter((e, i ,ar)=> i !== ar.indexOf(e)).includes(e)))
console.log(newArray) // output [1]
}
removeOccurences(["hello","hello","world",1,"world"])
I have an array of objects and I am removing elements based on object value, without knowing which element it is.
So... those lovely people who flagged my question as duplicate and suggest I read How do I remove a particular element from an array in JavaScript? are not helping.
My question... again...
I have an array of objects
I want to search and remove specific elements from the array. I have a solution that is long winded (loop thru the array once, make a list of element id's, then slice one by one in another loop). I am hoping there is another method (enhance my skillset too).
myarray.filter(function(item)
{
if( item.flag==="Y" )
{
// how to delete element from myarray
// delete implies remove it from myarray
}
});
All help appreciated =)
You have at least two options:
Create a new array with filter
The first is to create a new array containing only the entries you want. You're already on the right track with filter:
myArray = myArray.filter(function(item) {
return item.flag !== "Y";
});
The new array will only have the entries that the callback returned a truthy value for. In this case, only ones whose flag is !== "Y". Entries whose flag is === "Y" will be left out of it.
Note that if you have other references to this same array in other variables, they will continue to point to the old array. Only myArray (in the above) gets a reference to the new array.
Modify the existing array with splice and a loop
The second is to use a while loop and splice:
var n = 0;
while (n < myArray.length) {
if (myArray[n].flag === "Y") {
// Remove it
myArray.splice(n, 1);
} else {
// Move to next
++n;
}
}
Note we don't move to next if we remove one, because we need to test the one after it (which is now at the previous index).
Or as Nina points out in a comment, a for loop going backward:
for (var n = myArray.length - 1; n >= 0; --n) {
if (myArray[n].flag === "Y") {
// Remove it
myArray.splice(n, 1);
}
}
In that case, since we're modifying the array (not creating a new one), the changes will be visible through any reference to that same array, not just myArray. (Since they all point to the same object, which we modified the state of.)
Remove object in array by its property-value:
Remove value: 30:
arr.splice(arr.map(el => el.value).indexOf(30), 1);
DEMO
Remove name: "John":
arr.splice(arr.map(el => el.name).indexOf("John"), 1);
Let's say you have the follow array:
var array = ["app_angrybirds", "app_flappybird", "ilovebirds"];
How would you go about removing any array element that begins with the string "app_"?
for (var i = 0; i < array.length; i++) {
if(array[i].substr(0, 4) === "app_") {
array.splice(i, 1);
i--; //The index will be moved one forward at the end of the loop, but the whole array
//will be shifted, so we compensate by decrementing i
}
}
You can just loop through and check the first 4 characters (using substr) and compare it. If they match, remove the element using splice. We also use a small hack using i-- to keep the index pointing at the right place.
Explanation for the above:
The for loop steps through each element of the array. For each iteration, you compare the first four characters of the element,whose index matches with the iteration variable, to the string "app_". Here the array method substr(0,4) isolates the characters from the 0th element up to but not including the 4th element and makes the substring available for comparison with "app_".If the condition is true that the substring of the element matches with "app_" , use the splice() method to surgically remove the element from the array based on the parameters you pass to it, in this case the ith element.
This is the simplest way that I can think of:
var array = ["app_angrybirds", "app_flappybird", "ilovebirds"];
var result = array.filter(doesNotHave(/^app_/));
alert(JSON.stringify(result));
function doesNotHave(regex) {
return function (str) {
return !regex.test(str);
}
}
Hope that helps.
This is for a coderbyte challenge that I finished a while ago. Your function is supposed to get the second greatest and second lowest numbers heres what I originally used:
function SecondGreatLow(arr){
var sorted = arr.sort(function(a,b){
return a-b;
});
return sorted[1] + " " + sorted[arr.length - 2];
}
SecondGreatLow(readline());
I got two cases wrong with this function one of them being ([2,2,2,5,5,5,6]) because there are duplicate numbers. I implemented this into my new code :
function SecondGreatLow(arr) {
var exclude = [arr[0]];
for(var i = 1; i < arr.length; i++) {
if (exclude.indexOf(arr[i]) == -1) {
exclude.push(arr[i]);
}
}
return exclude
}
SecondGreatLow([33,33,33,44,44,44,55,55,6,4,3])
My question is how does this find all the duplicate numbers? Isn't the variable exclude(arr[0]) 33? I'm confused how this gets rid of all the duplicate numbers.
My question is how does this find all the duplicate numbers?
It actually doesn't find duplicate values, it collects unique values.
You iterate over the original array and add only values to exclude which are not already in exclude. That guarantees that every value in exclude is unique.
My question is how does it do this if exclude originally is only arr[0] or 33
This line:
var exclude = [arr[0]];
it just used to not start with an empty array. As you can see in the for statement
for(var i = 1; i < arr.length; i++) {
the code starts iterating at index 1, not 0. You could also just have started with an empty array:
var exclude = [];
for(var i = 0; i < arr.length; i++) {
but that's a bit wasteful since you know that the first value is going to be added to exclude anyway.
The way this code works is but adding new variables into the array exclude. It will only add the new variable if the current variable doesn't already exist in the array exclude.
The line:
exclude.indexOf(arr[i]) == -1
is what is doing main work.
It finds variable i and check if it already exists in the array exclude. If it does not exist indexOf returns -1, thus the if statement is true, and we go into the line
exclude.push(arr[i]);
and add the variable into the array exclude.
In the below loop
for(var i = 1; i < arr.length; i++) {
if (exclude.indexOf(arr[i]) == -1) {
exclude.push(arr[i]);
}
}
It is checking if the number from input array is already present in exclude if not it will insert that number to exclude.
The indexOf() method searches the array for the specified item, and returns its position. so in case of duplicate numbers it will not return -1 thus the logic above will skip adding that duplicate number to exculde variable. You can refer below for more details.
http://www.w3schools.com/jsref/jsref_indexof_array.asp