How do I access JQuery property inside a usual JS function - javascript

I have a function which takes an array as an argument and later process it and change values of this array. The problem is that the array was made of JQuery nodes(usual span), and I access this span value by calling .text() JQuery method. Here's how it looks:
var array=
[
$('*[id$=id1]'),
$('*[id$=id2]'),
$('*[id$=id3]'),
$('*[id$=id4]'),
$('*[id$=id5]')
] // Ignore the weird way of the selectors. It's just a feature of back-end technology I use
function removeZeros(arr)
{
var map = arr.map(function(a) {
//logic to perform...
}
arr.forEach(function(value, index, arr)
{
arr[index] = Number.parseFloat(value).toFixed(maxNum);
});
//Rewriting the values..
}
}
removeZeros(array)
In the example above I get an exception since the values which are stored in the array are just plain HTML code. The real value I access using .text() as I mentioned earlier. So I need to make the a in the function call this method.
I've tried (function($(a).text(), (function($(a.text()) and (function($a.text()) so far, but nothing seems to work, it throws a nasty exception of unexcepted literal. How do I access text() anyway?
Whole function:
function removeZeros(arr)
{
var map = arr.map(function(a)
{
if (a % 1 === 0)
{
var res = "1";
}
else
{
var lastNumman = a.toString().split('').pop();
if (lastNumman == 0)
{
var m = parseFloat(a);
var res = (m + "").split(".")[1].length;
}
else
{
var m = a.split(".")[1].length;
var res = m;
}
}
return res;
});
var maxNum = map.reduce(function(a, b) {
return Math.max(a, b);
});
arr.forEach(function(value, index, arr) {
arr[index] = Number.parseFloat(value.text()).toFixed(maxNum);
});
}

In the example above I get an exception since the values which are stored in the array are just plain HTML code.
No, they're jQuery instances. Calling Number.parseFloat on a jQuery instance is going to return NaN*.
You don't need to do anything special if you want to access the text, the entry is a jQuery object, just call .text() on it directly:
arr[index] = Number.parseFloat(value.text()).toFixed(maxNum);
// ---------------------------------^^^^^^^
* (because parseFloat will coerce the object to string, getting "[object Object]", and "[object Object]" cannot be parsed to a float)
Having seen the full function, as you said in a comment, you'll want to use .text on a as well. Here's that and some other notes:
function removeZeros(arr) {
var map = arr.map(function(a) {
var res, astNumman, m;
// *** Get the text of the entry
a = a.text();
if (a % 1 === 0) { // *** ? `a` is a string. This will coerce it to number and then do % on it.
res = "1";
} else {
lastNumman = a[a.length-1]; // *** Much more efficient than `a.split('').pop();`
if (lastNumman == 0) { // *** Again using a string as a number
m = parseFloat(a);
res = (m + "").split(".")[1].length; // *** The *length* of the fractional portion?
} else {
m = a.split(".")[1].length;
res = m;
}
}
return res;
});
var maxNum = map.reduce(function(a, b) {
return Math.max(a, b);
});
// ***
arr.forEach(function(value, index, arr) {
arr[index] = Number.parseFloat(value.text()).toFixed(maxNum);
});
}
Running Example:
var array=
[
$('*[id$=id1]'),
$('*[id$=id2]'),
$('*[id$=id3]'),
$('*[id$=id4]'),
$('*[id$=id5]')
];
function removeZeros(arr) {
var map = arr.map(function(a) {
var res, astNumman, m;
// *** Get the text of the entry
a = a.text();
if (a % 1 === 0) { // *** ? `a` is a string. This will coerce it to number and then do % on it.
res = "1";
} else {
lastNumman = a[a.length-1]; // *** Much more efficient than `a.split('').pop();`
if (lastNumman == 0) { // *** Again using a string as a number
m = parseFloat(a);
res = (m + "").split(".")[1].length; // *** The *length* of the fractional portion?
} else {
m = a.split(".")[1].length;
res = m;
}
}
return res;
});
var maxNum = map.reduce(function(a, b) {
return Math.max(a, b);
});
// ***
arr.forEach(function(value, index, arr) {
arr[index] = Number.parseFloat(value.text()).toFixed(maxNum);
});
}
removeZeros(array);
console.log(array);
<div id="id1">7</div>
<div id="id2">6.4324</div>
<div id="id3">8.24</div>
<div id="id4">8998.3</div>
<div id="id5">0</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
It seems like the goal of removeZeroes is to convert the array of jQuery objects into an array of strings with the text of the object converted to number and then to string where they all have the same number of digits after the decimal (the longest one). If so, we can be a bit more efficient about it:
function removeZeros(arr) {
// Find longest decimal portion, convert jQuery objects to numbers
var longest = -Infinity;
arr.forEach(function(entry, index) {
var num = parseFloat(entry.text());
var str = String(num);
var decimal = str.indexOf(".");
var thisLength;
if (decimal === -1) {
thisLength = 1;
} else {
thisLength = str.length - decimal - 1;
}
if (thisLength > longest) {
longest = thisLength;
}
arr[index] = num;
});
// Format numbers as strings
arr.forEach(function(num, index) {
arr[index] = num.toFixed(longest);
});
}
Running Example:
var array=
[
$('*[id$=id1]'),
$('*[id$=id2]'),
$('*[id$=id3]'),
$('*[id$=id4]'),
$('*[id$=id5]')
];
function removeZeros(arr) {
// Find longest decimal portion, convert jQuery objects to numbers
var longest = -Infinity;
arr.forEach(function(entry, index) {
var num = parseFloat(entry.text());
var str = String(num);
var decimal = str.indexOf(".");
var thisLength;
if (decimal === -1) {
thisLength = 1;
} else {
thisLength = str.length - decimal - 1;
}
if (thisLength > longest) {
longest = thisLength;
}
arr[index] = num;
});
// Format numbers as strings
arr.forEach(function(num, index) {
arr[index] = num.toFixed(longest);
});
}
removeZeros(array);
console.log(array);
<div id="id1">7</div>
<div id="id2">6.4324</div>
<div id="id3">8.24</div>
<div id="id4">8998.3</div>
<div id="id5">0</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
There I've used your arr.forEach-assign-to-arr[index] pattern rather than map as you seemed to prefer it (and it does avoid creating two unnecessary arrays).

Related

print like this * "a" -> "a1" * "aabbbaa" -> "a2b3a2"

I am new to js.
can you tell me how to print like this * "a" -> "a1" * "aabbbaa" -> "a2b3a2"
i tried with hash map but test cases failing.
providing my code below.
i am not good in hash map.
can you tell me how to solve with hash map so that in future I can fix it my self.
not sure what data structure to use for this one.
providing my code below.
const _ = require("underscore");
const rle = ( input ) => {
console.log("input--->" + input);
//var someString ="aaa";
var someString = input;
var arr = someString.split("");
var numberCount = {};
for(var i=0; i< arr.length; i++) {
var alphabet = arr[i];
if(numberCount[alphabet]){
numberCount[alphabet] = numberCount[alphabet] + 1;
}
else{
numberCount[alphabet] = 1;
}
}
console.log("a:" + numberCount['a'], "b:" + numberCount['b']);
}
/**
* boolean doTestsPass()
* Returns true if all the tests pass. Otherwise returns false.
*/
/**
* Returns true if all tests pass; otherwise, returns false.
*/
const doTestsPass = () => {
const VALID_COMBOS = {"aaa": "a3", "aaabbc":"a3b2c1"};
let testPassed = true;
_.forEach(VALID_COMBOS, function(value, key) {
console.log(key, rle(key));
if (value !== rle(key)) {
testPassed = false;
}
});
return testPassed;
}
/**
* Main execution entry.
*/
if(doTestsPass())
{
console.log("All tests pass!");
}
else
{
console.log("There are test failures.");
}
You could
match groups of characters,
get the character and the count and
join it to a string.
function runLengthEncoding(string) {
return string
.match(/(.)\1*/g) // keep same characters in a single string
.map(s => s[0] + s.length) // take first character of string and length
.join(''); // create string of array
}
console.log(['a', 'aaa', 'aaabbc'].map(runLengthEncoding));
This is a bit more understandable version which iterates the given string and count the characters. If a different character is found, the last character and count is added to the result string.
At the end, a check is made, to prevent counting of empty strings and the last character cound is added to the result.
function runLengthEncoding(string) {
var result = '',
i,
count = 0,
character = string[0];
for (i = 0; i < string.length; i++) {
if (character === string[i]) {
count++;
continue;
}
result += character + count;
character = string[i];
count = 1;
}
if (count) {
result += character + count;
}
return result;
}
console.log(['', 'a', 'aaa', 'aaabbc'].map(runLengthEncoding));
You can reduce the array into a multidimensional array. map and join the array to convert to string.
const rle = (input) => {
return input.split("").reduce((c, v) => {
if (c[c.length - 1] && c[c.length - 1][0] === v) c[c.length - 1][1]++;
else c.push([v, 1]);
return c;
}, []).map(o => o.join('')).join('');
}
console.log(rle("a"));
console.log(rle("aabbbaa"));
console.log(rle("aaaaaa"));
Your function rle doesn't return a result.
Also note, this implementation may pass the test cases you wrote, but not the examples you mentioned in your question: for the string "aabbaa" this will produce "a4b2", not " a2b2a2" .
A simpler solution:
function runLengthEncoding(str) {
let out = "";
for (let i = 0; i < str.length; ++i) {
let temp = str[i];
let count = 1;
while (i < str.length && str[i+1] == temp) {
++count;
++i;
}
out += temp + count;
} // end-for
return out;
}
console.log(runLengthEncoding("a"));
console.log(runLengthEncoding("aabbbaa"));
console.log(runLengthEncoding("aaaaaa"));

How to compare every number in an array against each other? (javascript)

I have a set of numbers which are displayed like followed;
var data = "615:415,600:400,600:400,300:300"
Each number represents an x/y coordinate, and I would like to add a value next to each one which is calculated based on the frequency of the number within a range.
So, I would like to be able to compare each value against all others in this string, and from this perform the following functions;
Remove the number from the string if it is a duplicate, and add :1
If the x/y numbers are both within a range of 15 against any other number, add:1
If there are no matches, add :0
Turn into array
So using the data string, it would be transformed to;
var data = "615:415:1, 600:400:2, 300:300:0"
I have been trying to do this using a reducer function, but I'm struggling with mainly step 2. I'm hoping someone can help out?
Thanks - Code + Plunk below!
http://plnkr.co/edit/zPW1844cLnUFAlEI77jq?p=preview
var result = [];
var data = "615:415,600:400,600:400,300:300"
var count = 0;
var reducer = function(p, c, i, a) {
if (p && p !== c) {
var _t = p.split(":");
result.push({
x: _t[0],
y: _t[1],
value: count
});
count = 0;
if (i === a.length - 1) {
_t = c.split(":");
result.push({
x: _t[0],
y: _t[1],
value: count
});
}
}
else {
count++;
}
return c
}
data.split(',').sort().reduce(reducer);
console.log(result)
You could use a step-by-step approach and split the string first in coordinates, generate a hash table for the coordinates with count and filter only unique coordinates.
Then compare each unique coordinates with each other and count if inside of a given range.
Later map the coordinates with the count and join to string.
var data = "615:415,600:400,600:400,300:300",
result = function (array) {
var i, j,
hash = Object.create(null),
unique = array.split(',').filter(function (a) {
var parts = a.split(':');
if (!hash[a]) {
hash[a] = [parts[0], parts[1], 0]; // [x, y, count]
return true;
}
hash[a][2]++;
});
for (i = 0; i < unique.length - 1; i++) {
for (j = i + 1; j < unique.length; j++) {
if (
Math.abs(hash[unique[i]][0] - hash[unique[j]][0]) <= 15 &&
Math.abs(hash[unique[i]][1] - hash[unique[j]][1]) <= 15
) {
hash[unique[i]][2]++;
hash[unique[j]][2]++;
}
}
}
return unique.map(function (a) {
return hash[a].join(':');
}).join(', ');
}(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's an alternative:
var data = "615:415,600:400,600:400,300:300";
var result = (function (s) {
var result = {};
var values = [];
// Process each value
s.split(',').forEach(function (v) {
var b = v.split(':');
// If a match, increment count by 2 (once for match and again for within 15)
if (result[v]) {
result[v].count += 2;
// Otherwise, just check for within 15
} else {
result[v] = {x:b[0], y:b[1], count:0};
values.forEach(function(xy, i){
if (xy[0]>= (b[0]-15) && xy[0] <= (+b[0]+15) &&
xy[1]>= (b[1]-15) && xy[1] <= (+b[1]+15) ) {
++result[xy.join(':')].count; // Increment for nearby only
}
})
values.push([b[0],b[1]]);
}
})
// Create required string format
return Object.keys(result).reduce(function(arr, key){
arr.push(key + ':' + result[key].count);
return arr;
},[]).join(', ');
})(data)
console.log(result);
All answers so far are good. I just would like to introduce a little variety by inventing an Array.prototype.withEachOther() method. Which just takes a callback an invokes the callback with each other item of the array being it's arguments as you may suggest. It works in place.
Array.prototype.withEachOther = function(cb){
this.map(function(e,i,a){
var t = a.slice();
t.splice(0,i+1);
t.map(function(f){
a[i] = cb(e,f);
});
});
return this;
};
var data = "615:415,600:400,600:400,300:300, 550 : 550".split(/\s*,\s*/)
.map(s => s.split(/\s*:\s*/).concat(0)),
cb = (f,s) => (Math.abs(f[0]-s[0]) <= 15 && Math.abs(f[1]-s[1]) <= 15 && (f[2]++, s[2]++),f);
result = data.reduceRight(function(p,c,i,a){
var fi = a.slice(0,i-a.length)
.findIndex(f => f[0] === c[0] && f[1] === c[1]);
fi !== -1 ? (a[fi][2] += ++c[2], a.splice(i,1))
: p.push(c);
return p;
},[])
.withEachOther(cb)
.reduce((p,c) => p += c[0]+":"+c[1]+":"+c[2]+", ","");
console.log(result);

Javascript Cannot call method 'indexOf' of undefined at order

I need to make a function that will sort a string. Each word in the String will contain a single number. Numbers can be from 1 to 9(no 0).
For example an input: "is2 Thi1s T4est 3a" the function should return "Thi1s is2 3a T4est".
My code is :
function order(words)
{
// ...
if(words == '')
{
return words;
}
var all_words = words.split(" ");
var checked_words = new Array();
var joined_words = "";
for(i = 1; i <= 9; i++)
{
//console.log(checked_words);
//checked_words[i-1] = all_words;
for(j = 1;j <= all_words.length; j++)
{
if(all_words[i-1].indexOf(i) != -1)
{
checked_words.push(all_words[i-1]);
if(i == (all_words.length))
{
joined_words = checked_words.join(" ");
return joined_words;
}
}
}
}
}
The problem is it kept showing "TypeError: Cannot call method 'indexOf' of undefined at order". Please help thanks!
I've been trying to figure out what that first loop is doing and I finally realised it's checking for the numbers in the string. You shouldn't do it that way because it's 1) weird, 2) non-peformant if it worked.
Instead use one loop and a regex to find the number in the string.
for (var i = 0; i < all_words.length; i++) {
// take the first match and coerce it to an integer
var n = +all_words[i].match(/\d+/)[0];
checked_words[n] = all_words[i];
}
// checked_words has an undefined element at index 0;
// slice takes a copy of the array from index 1
return checked_words.slice(1).join(' ');
DEMO
Alternatively you could use reduce.
var joined_words = str.split(' ').reduce(function (p, c) {
var n = +c.match(/\d+/)[0];
p[n] = c;
return p;
}, []).slice(1).join(' ');
DEMO
You're not even tied to the numbers 0-9. As long as you filter out the undefined elements, you're golden...
var str = 'is2 Thi1s T4est 3a Ye12s!';
var out = str.split(' ').reduce(function (p, c) {
var n = +c.match(/\d+/)[0];
p[n] = c;
return p;
}, []).slice(1).filter(function (el) {
return el !== undefined;
}).join(' ');
DEMO

How to find indices of all occurrences of one string in another in JavaScript?

I'm trying to find the positions of all occurrences of a string in another string, case-insensitive.
For example, given the string:
I learned to play the Ukulele in Lebanon.
and the search string le, I want to obtain the array:
[2, 25, 27, 33]
Both strings will be variables - i.e., I can't hard-code their values.
I figured that this was an easy task for regular expressions, but after struggling for a while to find one that would work, I've had no luck.
I found this example of how to accomplish this using .indexOf(), but surely there has to be a more concise way to do it?
var str = "I learned to play the Ukulele in Lebanon."
var regex = /le/gi, result, indices = [];
while ( (result = regex.exec(str)) ) {
indices.push(result.index);
}
UPDATE
I failed to spot in the original question that the search string needs to be a variable. I've written another version to deal with this case that uses indexOf, so you're back to where you started. As pointed out by Wrikken in the comments, to do this for the general case with regular expressions you would need to escape special regex characters, at which point I think the regex solution becomes more of a headache than it's worth.
function getIndicesOf(searchStr, str, caseSensitive) {
var searchStrLen = searchStr.length;
if (searchStrLen == 0) {
return [];
}
var startIndex = 0, index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>
One liner using String.prototype.matchAll (ES2020):
[...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index)
Using your values:
const sourceStr = 'I learned to play the Ukulele in Lebanon.';
const searchStr = 'le';
const indexes = [...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index);
console.log(indexes); // [2, 25, 27, 33]
If you're worried about doing a spread and a map() in one line, I ran it with a for...of loop for a million iterations (using your strings). The one liner averages 1420ms while the for...of averages 1150ms on my machine. That's not an insignificant difference, but the one liner will work fine if you're only doing a handful of matches.
See matchAll on caniuse
Here is regex free version:
function indexes(source, find) {
if (!source) {
return [];
}
// if find is empty string return all indexes.
if (!find) {
// or shorter arrow function:
// return source.split('').map((_,i) => i);
return source.split('').map(function(_, i) { return i; });
}
var result = [];
for (i = 0; i < source.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
return result;
}
indexes("I learned to play the Ukulele in Lebanon.", "le")
EDIT: and if you want to match strings like 'aaaa' and 'aa' to find [0, 2] use this version:
function indexes(source, find) {
if (!source) {
return [];
}
if (!find) {
return source.split('').map(function(_, i) { return i; });
}
var result = [];
var i = 0;
while(i < source.length) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
i += find.length;
} else {
i++;
}
}
return result;
}
You sure can do this!
//make a regular expression out of your needle
var needle = 'le'
var re = new RegExp(needle,'gi');
var haystack = 'I learned to play the Ukulele';
var results = new Array();//this is the results you want
while (re.exec(haystack)){
results.push(re.lastIndex);
}
Edit: learn to spell RegExp
Also, I realized this isn't exactly what you want, as lastIndex tells us the end of the needle not the beginning, but it's close - you could push re.lastIndex-needle.length into the results array...
Edit: adding link
#Tim Down's answer uses the results object from RegExp.exec(), and all my Javascript resources gloss over its use (apart from giving you the matched string). So when he uses result.index, that's some sort of unnamed Match Object. In the MDC description of exec, they actually describe this object in decent detail.
I am a bit late to the party (by almost 10 years, 2 months), but one way for future coders is to do it using while loop and indexOf()
let haystack = "I learned to play the Ukulele in Lebanon.";
let needle = "le";
let pos = 0; // Position Ref
let result = []; // Final output of all index's.
let hayStackLower = haystack.toLowerCase();
// Loop to check all occurrences
while (hayStackLower.indexOf(needle, pos) != -1) {
result.push(hayStackLower.indexOf(needle , pos));
pos = hayStackLower.indexOf(needle , pos) + 1;
}
console.log("Final ", result); // Returns all indexes or empty array if not found
If you just want to find the position of all matches I'd like to point you to a little hack:
var haystack = 'I learned to play the Ukulele in Lebanon.',
needle = 'le',
splitOnFound = haystack.split(needle).map(function (culm)
{
return this.pos += culm.length + needle.length
}, {pos: -needle.length}).slice(0, -1); // {pos: ...} – Object wich is used as this
console.log(splitOnFound);
It might not be applikable if you have a RegExp with variable length but for some it might be helpful.
This is case sensitive. For case insensitivity use String.toLowerCase function before.
const findAllOccurrences = (str, substr) => {
str = str.toLowerCase();
let result = [];
let idx = str.indexOf(substr)
while (idx !== -1) {
result.push(idx);
idx = str.indexOf(substr, idx+1);
}
return result;
}
console.log(findAllOccurrences('I learned to play the Ukulele in Lebanon', 'le'));
I would recommend Tim's answer. However, this comment by #blazs states "Suppose searchStr=aaa and that str=aaaaaa. Then instead of finding 4 occurences your code will find only 2 because you're making skips by searchStr.length in the loop.", which is true by looking at Tim's code, specifically this line here: startIndex = index + searchStrLen; Tim's code would not be able to find an instance of the string that's being searched that is within the length of itself. So, I've modified Tim's answer:
function getIndicesOf(searchStr, str, caseSensitive) {
var startIndex = 0, index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + 1;
}
return indices;
}
var searchStr = prompt("Enter a string.");
var str = prompt("What do you want to search for in the string?");
var indices = getIndicesOf(str, searchStr);
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>
Changing it to + 1 instead of + searchStrLen will allow the index 1 to be in the indices array if I have an str of aaaaaa and a searchStr of aaa.
P.S. If anyone would like comments in the code to explain how the code works, please say so, and I'll be happy to respond to the request.
Here is a simple code snippet:
function getIndexOfSubStr(str, searchToken, preIndex, output) {
var result = str.match(searchToken);
if (result) {
output.push(result.index +preIndex);
str=str.substring(result.index+searchToken.length);
getIndexOfSubStr(str, searchToken, preIndex, output)
}
return output;
}
var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var searchToken ="my";
var preIndex = 0;
console.log(getIndexOfSubStr(str, searchToken, preIndex, []));
Thanks for all the replies. I went through all of them and came up with a function that gives the first an last index of each occurrence of the 'needle' substring . I am posting it here in case it will help someone.
Please note, it is not the same as the original request for only the beginning of each occurrence. It suits my usecase better because you don't need to keep the needle length.
function findRegexIndices(text, needle, caseSensitive){
var needleLen = needle.length,
reg = new RegExp(needle, caseSensitive ? 'gi' : 'g'),
indices = [],
result;
while ( (result = reg.exec(text)) ) {
indices.push([result.index, result.index + needleLen]);
}
return indices
}
Check this solution which will able to find same character string too, let me know if something missing or not right.
function indexes(source, find) {
if (!source) {
return [];
}
if (!find) {
return source.split('').map(function(_, i) { return i; });
}
source = source.toLowerCase();
find = find.toLowerCase();
var result = [];
var i = 0;
while(i < source.length) {
if (source.substring(i, i + find.length) == find)
result.push(i++);
else
i++
}
return result;
}
console.log(indexes('aaaaaaaa', 'aaaaaa'))
console.log(indexes('aeeaaaaadjfhfnaaaaadjddjaa', 'aaaa'))
console.log(indexes('wordgoodwordgoodgoodbestword', 'wordgood'))
console.log(indexes('I learned to play the Ukulele in Lebanon.', 'le'))
Follow the answer of #jcubic, his solution caused a small confusion for my case
For example var result = indexes('aaaa', 'aa') will return [0, 1, 2] instead of [0, 2]
So I updated a bit his solution as below to match my case
function indexes(text, subText, caseSensitive) {
var _source = text;
var _find = subText;
if (caseSensitive != true) {
_source = _source.toLowerCase();
_find = _find.toLowerCase();
}
var result = [];
for (var i = 0; i < _source.length;) {
if (_source.substring(i, i + _find.length) == _find) {
result.push(i);
i += _find.length; // found a subText, skip to next position
} else {
i += 1;
}
}
return result;
}
Here's my code (using search and slice methods)
let s = "I learned to play the Ukulele in Lebanon"
let sub = 0
let matchingIndex = []
let index = s.search(/le/i)
while( index >= 0 ){
matchingIndex.push(index+sub);
sub = sub + ( s.length - s.slice( index+1 ).length )
s = s.slice( index+1 )
index = s.search(/le/i)
}
console.log(matchingIndex)
This is what I usually use to get a string index also according to its position.
I pass following parameters:
search: the string where to search for
find: the string to find
position ('all' by default): the position by which the find string appears in search string
(if 'all' it returns the complete array of indexes)
(if 'last' it returns the last position)
function stringIndex (search, find, position = "all") {
var currIndex = 0, indexes = [], found = true;
while (found) {
var searchIndex = search.indexOf(find);
if (searchIndex > -1) {
currIndex += searchIndex + find.length;
search = search.substr (searchIndex + find.length);
indexes.push (currIndex - find.length);
} else found = false; //no other string to search for - exit from while loop
}
if (position == 'all') return indexes;
if (position > indexes.length -1) return [];
position = (position == "last") ? indexes.length -1 : position;
return indexes[position];
}
//Example:
var myString = "Joe meets Joe and together they go to Joe's house";
console.log ( stringIndex(myString, "Joe") ); //0, 10, 38
console.log ( stringIndex(myString, "Joe", 1) ); //10
console.log ( stringIndex(myString, "Joe", "last") ); //38
console.log ( stringIndex(myString, "Joe", 5) ); //[]
Hi friends this is just another way of finding indexes of matching phrase using reduce and a helper method. Of course RegExp is more convenient and perhaps is internally implemented somehow like this. I hope you find it useful.
function findIndexesOfPhraseWithReduce(text, phrase) {
//convert text to array so that be able to manipulate.
const arrayOfText = [...text];
/* this function takes the array of characters and
the search phrase and start index which comes from reduce method
and calculates the end with length of the given phrase then slices
and joins characters and compare it whith phrase.
and returns True Or False */
function isMatch(array, phrase, start) {
const end = start + phrase.length;
return (array.slice(start, end).join('')).toLowerCase() ===
phrase.toLowerCase();
}
/* here we reduce the array of characters and test each character
with isMach function which takes "current index" and matches the phrase
with the subsequent character which starts from current index and
ends at the last character of phrase(the length of phrase). */
return arrayOfText.reduce((acc, item, index) => isMatch(arrayOfText, phrase,
index) ? [...acc, index] : acc, []);
}
findIndexesOfPhraseWithReduce("I learned to play the Ukulele in Lebanon.", "le");
function findIndexesOfPhraseWithReduce(text, phrase) {
const arrayOfText = [...text];
function isMatch(array, phrase, start) {
const end = start + phrase.length;
return (array.slice(start, end).join('')).toLowerCase() ===
phrase.toLowerCase();
}
return arrayOfText.reduce((acc, item, index) => isMatch(arrayOfText, phrase,
index) ? [...acc, index] : acc, []);
}
console.log(findIndexesOfPhraseWithReduce("I learned to play the Ukulele in Lebanon.", "le"));
function countInString(searchFor,searchIn){
var results=0;
var a=searchIn.indexOf(searchFor)
while(a!=-1){
searchIn=searchIn.slice(a*1+searchFor.length);
results++;
a=searchIn.indexOf(searchFor);
}
return results;
}
the below code will do the job for you :
function indexes(source, find) {
var result = [];
for(i=0;i<str.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
return result;
}
indexes("hello, how are you", "ar")
Use String.prototype.match.
Here is an example from the MDN docs itself:
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);
console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']

remove value from comma separated values string

I have a csv string like this "1,2,3" and want to be able to remove a desired value from it.
For example if I want to remove the value: 2, the output string should be the following:
"1,3"
I'm using the following code but seems to be ineffective.
var values = selectedvalues.split(",");
if (values.length > 0) {
for (var i = 0; i < values.length; i++) {
if (values[i] == value) {
index = i;
break;
}
}
if (index != -1) {
selectedvalues = selectedvalues.substring(0, index + 1) + selectedvalues.substring(index + 3);
}
}
else {
selectedvalues = "";
}
var removeValue = function(list, value, separator) {
separator = separator || ",";
var values = list.split(separator);
for(var i = 0 ; i < values.length ; i++) {
if(values[i] == value) {
values.splice(i, 1);
return values.join(separator);
}
}
return list;
}
If the value you're looking for is found, it's removed, and a new comma delimited list returned. If it is not found, the old list is returned.
Thanks to Grant Wagner for pointing out my code mistake and enhancement!
John Resign (jQuery, Mozilla) has a neat article about JavaScript Array Remove which you might find useful.
function removeValue(list, value) {
return list.replace(new RegExp(",?" + value + ",?"), function(match) {
var first_comma = match.charAt(0) === ',',
second_comma;
if (first_comma &&
(second_comma = match.charAt(match.length - 1) === ',')) {
return ',';
}
return '';
});
};
alert(removeValue('1,2,3', '1')); // 2,3
alert(removeValue('1,2,3', '2')); // 1,3
alert(removeValue('1,2,3', '3')); // 1,2
values is now an array. So instead of doing the traversing yourself.
Do:
var index = values.indexOf(value);
if(index >= 0) {
values.splice(index, 1);
}
removing a single object from a given index.
hope this helps
Here are 2 possible solutions:
function removeValue(list, value) {
return list.replace(new RegExp(value + ',?'), '')
}
function removeValue(list, value) {
list = list.split(',');
list.splice(list.indexOf(value), 1);
return list.join(',');
}
removeValue('1,2,3', '2'); // "1,3"
Note that this will only remove first occurrence of a value.
Also note that Array.prototype.indexOf is not part of ECMAScript ed. 3 (it was introduced in JavaScript 1.6 - implemented in all modern implementations except JScript one - and is now codified in ES5).
// Note that if the source is not a proper CSV string, the function will return a blank string ("").
function removeCsvVal(var source, var toRemove) //source is a string of comma-seperated values,
{ //toRemove is the CSV to remove all instances of
var sourceArr = source.split(","); //Split the CSV's by commas
var toReturn = ""; //Declare the new string we're going to create
for (var i = 0; i < sourceArr.length; i++) //Check all of the elements in the array
{
if (sourceArr[i] != toRemove) //If the item is not equal
toReturn += sourceArr[i] + ","; //add it to the return string
}
return toReturn.substr(0, toReturn.length - 1); //remove trailing comma
}
To apply it too your var values:
var values = removeVsvVal(selectedvalues, "2");
guess im too slow but here is what i would do
<script language="javascript">
function Remove(value,replaceValue)
{ var result = ","+value+",";
result = result.replace(","+replaceValue+",",",");
result = result.substr(1,result.length);
result = result.substr(0,result.length-1);
alert(result);
}
Remove("1,2,3",2)
</script>
adding , before and after the string ensure that u only remove the exact string u want
function process(csv,valueToDelete) {
var tmp = ","+csv;
tmp = tmp.replace(","+valueToDelete,"");
if (tmp.substr(0,1) == ',') tmp = tmp.substr(1);
return tmp;
}
use splice, pop or shift. depending on your requirement.
You could also have "find" the indexes of items in your array that match by using a function like the one found here : http://www.hunlock.com/blogs/Ten_Javascript_Tools_Everyone_Should_Have
var tmp = [5,9,12,18,56,1,10,42,'blue',30, 7,97,53,33,30,35,27,30,'35','Ball', 'bubble'];
// 0/1/2 /3 /4/5 /6 /7 /8 /9/10/11/12/13/14/15/16/17/ 18/ 19/ 20
var thirty=tmp.find(30); // Returns 9, 14, 17
var thirtyfive=tmp.find('35'); // Returns 18
var thirtyfive=tmp.find(35); // Returns 15
var haveBlue=tmp.find('blue'); // Returns 8
var notFound=tmp.find('not there!'); // Returns false
var regexp1=tmp.find(/^b/); // returns 8,20 (first letter starts with b)
var regexp1=tmp.find(/^b/i); // returns 8,19,20 (same as above but ignore case)
Array.prototype.find = function(searchStr) {
var returnArray = false;
for (i=0; i<this.length; i++) {
if (typeof(searchStr) == 'function') {
if (searchStr.test(this[i])) {
if (!returnArray) { returnArray = [] }
returnArray.push(i);
}
} else {
if (this[i]===searchStr) {
if (!returnArray) { returnArray = [] }
returnArray.push(i);
}
}
}
return returnArray;
}
or
var csv_remove_val = function(s, val, sep) {
var sep = sep || ",", a = s.split(sep), val = ""+val, pos;
while ((pos = a.indexOf(val)) >= 0) a.splice(pos, 1);
return a.join(sep);
}

Categories

Resources