document.querySelectorAll("table[id^='Table']");
This code selects all tables with the id of Table. But i want to select tables with id of Table2 OR Table7 (or any other numbers). How to do this with regex?
Edit: jQuery is not applicable in my case.
function getTables(tableNumbers) { // Usage: getTables([2, 7]) will return the tables with the ID 'Table2' and 'Table7'. (You can add more numbers; [2,7,3,6])
var allTables = document.querySelectorAll("table[id^='Table']");
var tablesWeWant = [];
for (var i = 0; i < allTables.length; i++) {
if (allTables[i].id.match(/Table[0-9]/)) {
tablesWeWant.push(allTables[i]);
}
}
for (var i = 0; i < tablesWeWant.length; i++) {
if (!tableNumbers.contains(tablesWeWant[i].id.substr(id.length - 1))) {
tableNumbers.splice(i, 1);
}
}
return tablesWeWant;
}
This should return all tables with an ID matching the regex /Table[0-9]/ and ending with a digit contained in the variable tableNumbders.
DISCLAIMER: I'm not a regex expert.
EDIT:
After editing a few times the code above became a bit too long, so I rewrote it like this:
function getTables(tableNumbers) {
var tablesWeWant = [];
for (var i = 0; i < tableNumbers.length; i++) {
tablesWeWant.push(document.querySelector("#Table" + tableNumbers[i]));
}
return tablesWeWant;
}
The second approach works: http://jsfiddle.net/qQ7VT/1/
Related
I'm trying to build a collaborative doc editor and implement operational transformation. Imagine we have a string that is manipulated simultaneously by 2 users. They can only add characters, not remove them. We want to incorporate both of their changes.
The original string is: catspider
The first user does this: cat<span id>spider</span>
The second user does this: c<span id>atspi</span>der
I'm trying to write a function that will produce: c<span id>at<span id>spi</span>der</span>
The function I've written is close, but it produces c<span id>at<span i</span>d>spider</span> codepen here
String.prototype.splice = function(start, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start);
};
function merge(saved, working, requested) {
if (!saved || !working || !requested) {
return false;
}
var diffSavedWorking = createDiff(working, saved);
var diffRequestedWorking = createDiff(working, requested);
var newStr = working;
for (var i = 0; i < Math.max(diffRequestedWorking.length, diffSavedWorking.length); i++) {
//splice does an insert `before` -- we will assume that the saved document characters
//should always appear before the requested document characters in this merger operation
//so we first insert requested and then saved, which means that the final string will have the
//original characters first.
if (diffRequestedWorking[i]) {
newStr = newStr.splice(i, diffRequestedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffRequestedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
if (diffSavedWorking[i]) {
newStr = newStr.splice(i, diffSavedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffSavedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
}
return newStr;
}
//arr1 should be the shorter array.
//returns inserted characters at their
//insertion index.
function createDiff(arr1, arr2) {
var diff = [];
var j = 0;
for (var i = 0; i < arr1.length; i++) {
diff[i] = "";
while (arr2[j] !== arr1[i]) {
diff[i] += arr2[j];
j++;
}
j++;
}
var remainder = arr2.substr(j);
if (remainder) diff[i] = remainder;
return diff;
}
function insertNatX(arr, length, pos) {
for (var j = 0; j < length; j++) {
arr.splice(pos, 0, "");
}
}
var saved = 'cat<span id>spider</span>';
var working = 'catspider';
var requested = 'c<span id>atspi</span>der';
console.log(merge(saved, working, requested));
Would appreciate any thoughts on a better / simpler way to achieve this.
how do I count the frequency of the elements in the array, I'm new to Javascript and completely lost, I have looked at other answers here but can't get them to work for me. Any help is much appreciated.
function getText() {
var userText;
userText = document.InputForm.MyTextBox.value; //get text as string
alphaOnly(userText);
}
function alphaOnly(userText) {
var nuText = userText;
//result = nuText.split("");
var alphaCheck = /[a-zA-Z]/g; //using RegExp create variable to have only alphabetic characters
var alphaResult = nuText.match(alphaCheck); //get object with only alphabetic matches from original string
alphaResult.sort();
var result = freqLet(alphaResult);
document.write(countlist);
}
function freqLet(alphaResult) {
count = 0;
countlist = {
alphaResult: count
};
for (i = 0; i < alphaResult.length; i++) {
if (alphaResult[i] in alphaResult)
count[i] ++;
}
return countlist;
}
To count frequencies you should use an object which properties correspond to the letters occurring in your input string.
Also before incrementing the value of the property you should previously check whether this property exists or not.
function freqLet (alphaResult) {
var count = {};
countlist = {alphaResult:count};
for (i = 0; i < alphaResult.length; i++) {
var character = alphaResult.charAt(i);
if (count[character]) {
count[character]++;
} else {
count[character] = 1;
}
}
return countlist;
}
If you can use a third party library, underscore.js provides a function "countBy" that does pretty much exactly what you want.
_.countBy(userText, function(character) {
return character;
});
This should return an associative array of characters in the collection mapped to a count.
Then you could filter the keys of that object to the limited character set you need, again, using underscore or whatever method you like.
Do as below:
var __arr = [6,7,1,2,3,3,4,5,5,5]
function __freq(__arr){
var a = [], b = [], prev
__arr.sort((a,b)=>{return a- b} )
for(let i = 0; i<__arr.length; i++){
if(__arr[i] !== prev){
a.push(__arr[i])
b.push(1)
}else{
b[b.length - 1]++
}
prev = __arr[i]
}
return [a , b]
}
var myArr=["test1.nameA", "test1.nameB", "test2.nameC", "test2.nameA"];
I want to get those strings which start with "test1."
I have tried the following:
1)could you please let me know why I'm still getting all of the strings in the array?
for (var i = 0; i < myArr.length; i++) {
if ((myArr[i]).search(new RegExp("test1") != -1)) {
console.log(myArr[i]);
}
}
but this one is returning all elements! What am I doing wrong?
2) Also is it possible to check that it only starts with "test1" not just contains!
Updated the question:
myArr=["test1.nameA", "test1.nameB", "test2.nameC", "test2.nameA"];
var input="test1";
for (var i = 0; i < myArr.length; i++) {
if(myArr[i].search( new RegExp (/input/)) != -1) {
console.log(myArr[i]);
}
}
Thanks! Please let me know if you need more clarifications
You can keep only the values that match a regexp using Array.prototype.filter like this:
myArr.filter(function (i) { return /^test1\./.test(i); })
And to check that something just beggins with a string use /^string/. Note the ^
You are testing the value of new RegExp("test1")
if ((myArr[i]).search(new RegExp("test1") != -1)) {
^^^^^^^^^^^^^^^^^^^^^^^^^
And new RegExp("test1") will never equal -1, which mean your test is always true.
This is what you need:
var myArr=["test1.nameA", "test1.nameB", "test2.nameC", "test2.nameA"];
for (var i = 0; i < myArr.length; i++) {
if ((myArr[i]).search(new RegExp("test1")) != -1) {
console.log(myArr[i]);
}
}
Or better still, to avoid creating a new RegExp every time around the loop:
var myArr=["test1.nameA", "test1.nameB", "test2.nameC", "test2.nameA"];
var rex = new RegExp("test1");
for (var i = 0; i < myArr.length; i++) {
if ((myArr[i]).search(rex) != -1) {
console.log(myArr[i]);
}
}
Additionally, .search() returns the position that the expression is found in the string, and -1 if it isn't found. So when it returns zero, that means it's found at the start.
You could just test the values against the same RegExp.
var myArr=["test1.nameA", "test1.nameB", "test2.nameC", "test2.nameA"];
var pattern = /^test1\./; // begins with test1 followed by a dot
for(var i = 0; i < myArr.length; i++) {
if(pattern.test(myArr[i])) {
console.log(myArr[i]);
}
}
Working example: http://jsbin.com/qilinohora/1/edit?js,console
I want to get all the variations of a certain string. This string will be broken up by dashes. And the letters can only vary within those dashes.
For instance, let's say I pass DFI3-334-FG12 then I want to get all variations of that string for instance:
FI3-334-G12
FI3-334-F12
FI3-334-FG2
FI3-334-FG1
DI3-334-G12
DI3-334-F12
DI3-334-FG2
DI3-334-FG1
DF3-334-G12
DF3-334-F12
DF3-334-FG2
DF3-334-FG1
DFI-334-G12
DFI-334-F12
DFI-334-FG2
DFI-334-FG1
Can anyone assist with this? I have attempted loops but I only get as far as breaking it up and getting different parts of it:
FI3,DI3,DF3,DFI
334
G12,F12,FG2,FG1
This is my code:
$('#filter').on('click',function() {
var input = $('#code').val();
var parts = input.split("-");
var fixed = Array();
for(var i=0;i<parts.length; i++) {
if(parts[i].length != 3) {
k = 0;
fixed[i] = new Array();
for(var c=0;c<parts[i].length;c++) {
fixed[i][k] = parts[i].replace(parts[i].charAt(c),"");
k++;
}
} else {
fixed[i] = parts[i];
}
}
var final = Array();
$.each(fixed,function(i) {
$('#code_result').append(fixed[i] + "<br>");
})
});
If you know how many segments there are (3 in this case), you can use loops to get every possible combination.
See my example here:
http://jsfiddle.net/a6647m9e/1/
for(var i=0; i<parts[0].length; ++i) {
for(var j=0; j<parts[1].length; ++j) {
for(var k=0; k<parts[2].length; ++k) {
strings.push(parts[0][i]+'-'+parts[1][j]+'-'+parts[2][k]);
}
}
}
And just so you know, you're looking at (2^parts[0].length - 1) * (2^parts[1].length - 1) * (2^parts[2].length - 1) combinations (1575 in this case), taking out the blank combinations.
Note: this is all dependent on what your definition of "all possible combinations" is.
var string= 'DFI3-334-FG12';
var parts = string.split('-');
for(var i=0;i<parts[0].length;i++)
for(var j=0;j<parts[2].length;j++){
p1 = parts[0].substring(0,i)+parts[0].substring(i+1,parts[0].length);
p2 = parts[2].substring(0,j)+parts[2].substring(j+1,parts[2].length);
console.log(p1+'-'+parts[1]+'-'+p2);
}
I have a column of cells in a particular sheet of Google Spreadsheet document.
This column references multiple values in another sheet using the built-in JOIN command:
=JOIN(", ",Regular!B3,Regular!B9,Regular!B10,Regular!B11,Regular!B12,Regular!B13,Regular!B14)
typical output for each such cell is a list of integers that are comma-separated, f.ex:
2, 5, 10, 12, 13
Some cells use ranges like this:
=JOIN(", ",Regular!B3:B9)
I want to lock these cells in the formula as such: Regular!$B$3,Regular!$B:$9...
Right now I want each reference to lock both column and row, but a solution that lets me pick row, column or both is a better solution.
1) I haven't found a way to do this without using a custom script - have I missed something?
2) My custom script solution is unfinished:
function eachCellInRange(range, op) {
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
for (var i = 1; i <= numRows; i++) {
for (var j = 1; j <= numCols; j++) {
op(range.getCell(i,j), i, j);
}
}
};
function lockCell(cell, row, col) {
var formula = cell.getFormula();
if(formula) {
var startIdx = formula.indexOf('(');
if(startIdx > 0) {
//!! REGEX HERE !! //
cell.setValue(formula);
}
}
}
function lockRows() {
var range = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveRange();
eachCellInRange(range, lockCell);
};
I need to make a regex pattern that will identify the B3, B9... parts of the formula and change them to $B$3, $B$9... but also not break in the B1:B8 case
Currently all references are prefixed with SheetName! (e.g. Regular!B9:B20), in the future some may not be, so the most general solution is preferred.
I'm not sure whether this is what you're looking for but I would replace the little bit you currently have:
if(formula) {
var startIdx = formula.indexOf('(');
if(startIdx > 0) {
//!! REGEX HERE !! //
cell.setValue(formula);
}
}
by
if(formula.substring(0,6) == "=JOIN(") {
formula = formula.replace(/([A-Z]+(?=[0-9]))/g, function($1) {
return "$" +$1 + "$";
});
alert(formula);
// cell.setValue(formula);
}
Which ensures that the formula is a JOIN formula.
Also, I'm not that familiar with JS, but I put it in JSFiddle to see how it goes.
Warning: This will fail if your sheet names have alphanumeric characters (mix of letters and digits).
Using #Jerry's useful answer, I was able to suit it to my needs:
function eachCellInRange(range, op) {
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
for (var i = 1; i <= numRows; i++) {
for (var j = 1; j <= numCols; j++) {
op(range.getCell(i,j), i, j);
}
}
};
var lockOn = 1, lockOff = -1, lockNop = 0,
lockChar = '$', lockEmpty = '';
function lock2char(newLock, curLock) {
if(newLock == lockNop) newLock = curLock;
return (newLock > lockNop) ? lockChar : lockEmpty;
}
function bool2lock(boolValue) {
return (boolValue) ? lockOn : lockOff;
}
function lockCell(lockCol, lockRow, cell, row, col) {
var formula = cell.getFormula();
if(formula) {
var startIdx = formula.indexOf('(');
if(startIdx > 0) {
var newFormula = formula.replace(/([A-Z|\$]+(?=[0-9]))/g, function(part) {
var prefix = lock2char(lockCol, (part.charAt(0) == lockChar));
var suffix = lock2char(lockRow, (part.charAt(part.length -1) == lockChar));
part = part.replace(/\$/g, '');
return prefix + part + suffix;
});
cell.setFormula(newFormula);
}
}
}
function lockRows() {
var range = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveRange();
eachCellInRange(range, lockCell.bind(this, lockOff, lockOn));
};