function str_replace(str , part_to_replace , replace_with) {
var res = str.replace(part_to_replace , replace_with);
return res;
}
console.log(str_replace("amir" , "ir" , "er")) //returns "amer"
I want the function to return "e" which is the only part that changed aka replaced part so how i am supposed to do that ?
thanks in advance.
You could iterate all characters and take only the changed ones.
function check(a, b) {
if (a.length !== b.length) { return; }
return b
.split('') // take an array
.filter(function (c, i) { // filter
return a[i] !== c; // check characters
})
.join(''); // return string
}
function str_replace(str, part_to_replace, replace_with) {
return str.replace(part_to_replace, replace_with);
}
console.log(str_replace("amir", "ir", "er"));
console.log(check("amir", str_replace("amir", "ir", "er")));
It looks like you want an array of characters in the new string that were not present in the old one. This will do the trick:
function getDifference(oldStr, newStr) {
// .split('') turns your string into an array of characters
var oldSplit = oldStr.split('');
var newSplit = newStr.split('');
// then compare the arrays and get the difference
var diff = [];
for (var i = 0; i < newSplit.length; i++) {
if (newSplit[i] !== oldSplit[i]) {
diff.push(newSplit[i]);
}
}
return diff;
}
var diff = getDifference('amir', str_replace('amir', 'ir', 'er'));
console.log(diff); // e
Related
I tried to do this by resetting loop going trough firstword every time its letter matches with secondword letter.
function mutation(arr) {
var compare = [];
var firstword = arr[0].toLowerCase();
var secondword = arr[1].toLowerCase();
var j = 0;
for (let i = 0; i < firstword.length; i++) {
if (firstword[i] === secondword[j]) {
compare.push(secondword[i]);
i = -1;
j++;
}
}
let result = compare.join("")
if (result.length === secondword.length) {
return true;
} else {
return false;
}
}
console.log(mutation(["Noel", "Ole"]));
It works in some cases but in others, like above example, it doesn't. What seems to be the problem?
You need to compare.push(secondword[j]) instead of compare.push(secondword[i])
function mutation(arr) {
var compare = [];
var firstword = arr[0].toLowerCase();
var secondword = arr[1].toLowerCase();
var j = 0;
for (let i = 0; i < firstword.length; i++) {
if (firstword[i] === secondword[j]) {
compare.push(secondword[j]); // Correction here
i = -1;
j++;
}
}
let result = compare.join("");
if (result.length === secondword.length) {
return true;
} else {
return false;
}
}
console.log(mutation(["Noel", "Ole"]));
Also, you can consider using Array.prototype.every.
const mutation = ([first, sec]) => {
const lowerCaseFirst = first.toLowerCase();
const lowerCaseSec = sec.toLowerCase();
return Array.from(lowerCaseSec).every((ch) => lowerCaseFirst.includes(ch));
};
console.log(mutation(["Noel", "Ole"]));
If the strings are small then String.prototype.includes works fine but if they are large then you should consider using a Set.
const mutation = ([first, sec]) => {
const firstSet = new Set(first.toLowerCase());
const lowerCaseSec = sec.toLowerCase();
return Array.from(lowerCaseSec).every((ch) => firstSet.has(ch));
};
console.log(mutation(["Noel", "Ole"]));
Simple ES6 Function, we check with .every() if every characters of secondword is includes inside firstword. It return true if it does.
function mutation(arr) {
const firstword = arr[0].toLowerCase();
const secondword = arr[1].toLowerCase();
return secondword.split('').every(char => firstword.includes(char));
}
console.log(mutation(["Noel", "Ole"]));
The use of Set in SSM's answer works if you don't need to account for duplicate characters in the second string. If you do, here's an implementation that uses a Map of character counts. The map key is the character from string 1 and the value is the number of occurrences. For instance, if you want ["Noel", "Ole"] to return true, but ["Noel", "Olle"] to return false (string 1 does not contain 2 "l" characters). String 2 is then iterated through and character counts decremented if they exist. As soon as a character is not present or the count falls below 1 in the map, the function returns false.
function mutation(arr: string[]): boolean {
return s1ContainsAllCharsInS2(arr[0].toLowerCase(), arr[1].toLowerCase());
}
function s1ContainsAllCharsInS2(s1: string, s2: string): boolean {
if (s2.length > s1.length) {
return false;
}
let charCountMap: Map<string, number> = new Map<string, number>();
Array.from(s1).forEach(c => {
let currentCharCount: number = charCountMap.get(c);
charCountMap.set(c, 1 + (currentCharCount ? currentCharCount : 0));
});
return !Array.from(s2).some(c => {
let currentCharCount: number = charCountMap.get(c);
if (!currentCharCount || currentCharCount < 1){
return true;
}
charCountMap.set(c, currentCharCount - 1);
});
}
A different approach.
Mapping the characters and comparing against that map.
function mutation(arr) {
const chars = {};
for (let char of arr[0].toLowerCase()) {
chars[char] = true;
}
for (let char of arr[1].toLowerCase()) {
if (!chars[char]) {
return false;
}
}
return true;
}
console.log(mutation(["Noel", "Ole"]));
console.log(mutation(["Noel", "Oleeeeeeeeeeeee"]));
If the count also matters (your code doesn't take it into account) you can count the number of occurrences of each character and comparing these counts.
function mutation(arr) {
const chars = {};
for (let char of arr[0].toLowerCase()) {
chars[char] = (chars[char] || 0) + 1;
}
for (let char of arr[1].toLowerCase()) {
// check if chars[char] contains a (not empty == positive) count
// then decrement it for future checks
if (!chars[char]--) {
return false;
}
}
return true;
}
console.log(mutation(["Noel", "Ole"]));
console.log(mutation(["Noel", "Oleeeeeeeeeeeee"]));
// Create a function that takes a string and turns it into a Mexican Wave.
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++)
{
if(smallarr[j][j].toUpperCase()==smallarr[j][j])
{
var c=smallarr[j][j].toLowerCase()
smallarr[j][j]=c
}
else {
var c=smallarr[j][j].toUpperCase()
smallarr[j][j]=c}
}
}
return smallarr
}
document.write(wave("edabit"))
//console.log(smallarr)
The output I expect is wave("edabit") ➞ ["Edabit", "eDabit", "edAbit", "edaBit", "edabIt", "edabiT"] but now the output is the same as the input.
Any advice is appreciated.
You can split the input string into an array of characters and then map over it replacing the current character with it's uppercase version:
const wave = (str) => {
return str
.split('')
.map((char, index) =>
str.substr(0, index) + char.toUpperCase() + str.substr(index + 1))
}
console.log(wave('edabit'));
You can use Array.from() to create an array from the string. In the callback (mapFn) get the current letter, and the current index, use them with String.substring() to build a new string with the uppercased letter.
const fn = str => Array.from(str, (c, i) =>
str.substring(0, i) + c.toUpperCase() + str.substring(i + 1)
);
const result = fn('edabit');
console.log(result);
You can try double Array.map() where second callback argument represents an index:
let input = "edabit";
let result = input.split('').map(
(_, i) => input.split('').map(
(char, j) => i === j ? char.toUpperCase() : char).join()
);
console.log(result);
EDIT:
The problem with your approach is that strings are immutable so you need to build a new string using slice like below:
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++){
smallarr[j] = smallarr[j].slice(0,j) + smallarr[j][j].toUpperCase() + smallarr[j].slice(j+1);
}
return smallarr
}
document.write(wave("edabit"))
console.log(smallarr)
or just using one loop:
function wave(str){
var smallarr=[]
for (var i=0;i<str.length;i++){
smallarr.push(str.slice(0,i) + str[i].toUpperCase() + str.slice(i+1))
}
return smallarr
}
console.log(wave("edabit"))
The main issue with your code is that you try to update a character in a string, but that is not possible. In JavaScript strings are immutable. Trying to assign to a certain index will have no effect to the string.
Instead you must rebuild a string where that one character is different. You can use slice to take parts of the string to help you build it.
Here is your code adapted to that effect:
function wave(str) {
var smallarr = []; // define as local
for (var j = 0; j < str.length; j++) {
let c = str[j]; // Use a variable to avoid duplicate code
if (c.toUpperCase() === c) {
c = c.toLowerCase();
} else {
c = c.toUpperCase();
}
// You cannot modify a string; you need to regenerate one
smallarr.push(str.slice(0, j) + c + str.slice(j+1));
}
return smallarr
}
console.log(wave("edabit"))
String.prototype.replaceAt=function(index, char) {
var a = this.split("");
a[index] = char;
return a.join("");
}
const createEdibet = ( word ) => {
console.log('word ' + word.split(''));
let array = word.split('')
array.map((letter, i) => {
let a = word.replaceAt(i, letter.toUpperCase());
console.log(a);
return a;
});
console.log(array)
// console.log(words)
}
createEdibet('edabit');
You could split the string, map the array and take the splittes string for another mapping by checking the index and use an upper case letter for matching indices.
const
wave = (string) => string
.split('')
.map((_, i, splitted) => splitted.map((c, j) => i === j ? c.toUpperCase() : c).join(''));
};
console.log(wave('edabit'));
A classic approach
function wave(string) {
var result = [],
i, j, temp;
for (i = 0; i < string.length; i++) {
temp = '';
for (j = 0; j < string.length; j++) {
temp += i === j ? string[j].toUpperCase() : string[j];
}
result.push(temp);
}
return result;
}
console.log(wave('edabit'));
If the array length is small you can use split, map, join like this:
let text = `edabit`;
let results = text.split('').map((char,index,original)=>{
let temp = [...original];
temp[index]=temp[index].toUpperCase();
return temp.join('');
});
console.log(results);
But in big array it's not optimized.
In javascript if any variable has multiple values seperated by comma within double quotes,then how to check that values are same or not
var str= "0,1,-1";
How to check this variable.
The author wants to compare these 3 values. You most separate this variable with split:
var str= "0,1,-1",
arr = str.split(',');
all are same or not ie, true are false compare this array with function every
var str= "0,1,-1",
arr = str.split(',');
var res = arr.every(function (item) {
return item == arr[0];
})
console.log(res);
Short solution using String.prototype.split() and Set object:
var hasSameValues = function (s) {
return (new Set(s.split(','))).size === 1;
};
console.log(hasSameValues("0,1,-1"));
console.log(hasSameValues("1,1,1"));
console.log(hasSameValues("2,-2,2"));
you can split and then check for every item in splitted array.
check the fiddle
code is below -
var val = "1, 01, 0001";
var result = function(val)
{
var l = val.length;
if(l == 0)
{
return false;
}
else
{
//because all the values in 'val' fields are number
var f = Number.parseInt(val[0]) ;
for(i=1; i< l; i++)
{
if(Number.parseInt(val[i]) != f)
{
return false;
}
}
return true;
}
}(val.split(','))
alert(result);
I am making a piece of code for a website that will have a list of names in an array and pick a random name, I want to add a feature that will let the user add or delete a name from the array. I have all of these features but when deleting a name, the user has to type the name to match the Case in the array. I tried to make the so it would be Case-Insensitive, what am I doing wrong?
<html>
<!--Other code uneeded for this question-->
<p id="canidates"></p>
<body>
<input type="text" id="delname" /><button onclick="delName()">Remove Name from List</button>
<script>
//Array of names
var names = [];
//Other code uneeded for this question
//List of Canidates
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
//Other code uneeded for this question
//Remove name from Array
function delName() {
var dnameVal = document.getElementById('delname').value;
var pos = names.indexOf(dnameVal);
var namepos = names[pos]
var posstr = namepos.toUpperCase();
var dup = dnameVal.toUpperCase();
if(dup != posstr) {
alert("Not a valid name");
}
else {
names.splice(pos, 1);
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
}
}
</script>
</body>
</html>
ES2015 findIndex:
var array = ['I', 'hAve', 'theSe', 'ITEMs'],
indexOf = (arr, q) => arr.findIndex(item => q.toLowerCase() === item.toLowerCase());
console.log( indexOf(array, 'i') ) // 0
console.log( indexOf(array, 'these') ) // 2
console.log( indexOf(array, 'items') ) // 3
In ECMA-262, 5th edition, you could use Array.prototype.some for this.
var array = [ 'I', 'hAve', 'theSe', 'ITEMs' ];
var query = 'these'.toLowerCase();
var index = -1;
array.some(function(element, i) {
if (query === element.toLowerCase()) {
index = i;
return true;
}
});
// Result: index = 2
Easy way would be to have a temporary array that contains all the names in uppercase. Then you can compare the user input. So your code could become somthing like this:
function delName() {
var dnameVal = document.getElementById('delname').value;
var upperCaseNames = names.map(function(value) {
return value.toUpperCase();
});
var pos = upperCaseNames.indexOf(dnameVal.toUpperCase());
if(pos === -1) {
alert("Not a valid name");
}
else {
names.splice(pos, 1);
document.getElementById('canidates').innerHTML =
"<strong>List of Canidates:</strong> " + names.join(" | ");
}
}
Hope this helps solve your problem.
The most elegant solution would be to convert the array into a string first, then do a case insensitive comparison. For example:
var needle = "PearS"
var haystack = ["Apple", "banNnas", "pEArs"];
var stricmp = haystack.toString().toLowerCase(); // returns
// "apple,bananas,pears"
if (stricmp.indexOf(needle.toLowerCase()) > -1) {
// the search term was found in the array
} else {
// the search term was not found in the array
}
Probably best to create your own custom indexOf method, something like this.
'use strict';
var customIndexOf = function(arrayLike, searchElement) {
var object = Object(arrayLike);
var length = object.length >>> 0;
var fromIndex = arguments.length > 2 ? arguments[2] >> 0 : 0;
if (length < 1 || typeof searchElement !== 'string' || fromIndex >= length) {
return -1;
}
if (fromIndex < 0) {
fromIndex = Math.max(length - Math.abs(fromIndex), 0);
}
var search = searchElement.toLowerCase();
for (var index = fromIndex; index < length; index += 1) {
if (index in object) {
var item = object[index];
if (typeof item === 'string' && search === item.toLowerCase()) {
return index;
}
}
}
return -1;
};
var names = [
'John',
'Anne',
'Brian'
];
console.log(customIndexOf(names, 'aNnE'));
Or even
'use strict';
var customIndexOf = function(array, searchElement, fromIndex) {
return array.map(function(value) {
return value.toLowerCase();
}).indexOf(searchElement.toLowerCase(), fromIndex);
};
var names = [
'John',
'Anne',
'Brian'
];
console.log(customIndexOf(names, 'aNnE'));
You may also want to add more checks to be sure that each element in the array is actually a String and that the searchElement is also actually a String too. If pre-ES5 then load appropriate shims
You can use Array.prototype.find()
found = myArray.find(key => key.toUpperCase() === searchString.toUpperCase()) != undefined;
Example:
myArray = ['An', 'aRRay', 'oF', 'StringS'];
searchString = 'array';
found = myArray.find(key => key.toUpperCase() === searchString.toUpperCase()) != undefined;
if (found ) {
// The array contains the search string
}
else {
// Search string not found
}
Note: Array cannot contain undefined as a value.
It is possible using by map method. For example see below code
var _name = ['prasho','abraham','sam','anna']
var _list = [{name:'prasho'},{name:'Gorge'}];
for(var i=0;i<_list.length;i++)
{
if(_name.map(function (c) {
return c.toLowerCase();
}).indexOf(_list[i].name.toLowerCase()) != -1) {
//do what ever
}else{
//do what ever
}
}
More info
I needed something similar to this where I needed compare two strings using includes and needed to be able to support both case and case insensitive searches so I wrote the following small function
function compare(l1: string, l2: string, ignoreCase = true): boolean {
return (ignoreCase ? l1.toLowerCase() : l1).includes((ignoreCase ? l2.toLowerCase() : l2));
}
Same principle could apply to indexOf as below
function indexOf(l1: string, l2: string, ignoreCase = true): number {
return (ignoreCase ? l1.toLowerCase() : l1).indexOf((ignoreCase ? l2.toLowerCase() : l2));
}
I know this is not specifically Array.indexOf but hope this helps someone out if the come across this post on their travels.
To answer the ops question though, you can apply this similarly to an array combined with this answer from #ULIT JAIDEE (the slight change to this was using the tilda character as a separator in case any of the array values contained spaces)
function compare(l1: any[], l2: any[], ignoreCase = true): boolean {
return (ignoreCase ? l1.join('~').toLowerCase().split('~') : l1).indexOf((ignoreCase ? l2.join('~').toLowerCase().split('~') : l2));
}
Again hope this helps.
Turn the array into a string separated by a delimiter, turn that string lowercase, and then split the string back into an array by the same delimiter:
function findIt(arr, find, del) {
if (!del) { del = '_//_'; }
arr = arr.join(del).toLowerCase().split(del);
return arr.indexOf(find.toLowerCase());
}
var arr = ['Tom Riddle', 'Ron Weasley', 'Harry Potter', 'Hermione Granger'];
var find = 'HaRrY PoTtEr';
var index = findIt(arr, find);
if (~index) {
alert('Found ' + arr[index] + '! :D');
} else {
alert('Did not find it. D:');
}
This is the shortest one.
haystack.join(' ').toLowerCase().split(' ').indexOf(needle.toLowerCase())
// unique only, removes latter occurrences
array.filter((v, i, a) => a.findIndex(j => v.toLowerCase() === j.toLowerCase()) === i);
To improve on #vsync answer and handle mixed content in the array here is my take. (I understand the OP is about case-sensitive thus it implies strings, maybe :)
var array = ['I', 'hAve', 7, {}, 'theSe', 'ITEMs'],
Contains = (arr, q) =>
arr.findIndex((item) => q.toString().toLowerCase() === item.toString().toLowerCase());
console.log(Contains(array, 'i'));
console.log(Contains(array, 'x'));
console.log(Contains(array, {} ));
console.log(Contains(array, 7 ));
You can't make it case-insensitive. I'd use an object instead to hold a set of names:
function Names() {
this.names = {};
this.getKey = function(name) {
return name.toLowerCase();
}
this.add = function(name) {
this.names[this.getKey(name)] = name;
}
this.remove = function(name) {
var key = this.getKey(name);
if (key in this.names) {
delete this.names[key];
} else {
throw Error('Name does not exist');
}
}
this.toString = function() {
var names = [];
for (var key in this.names) {
names.push(this.names[key]);
}
return names.join(' | ');
}
}
var names = new Names();
function update() {
document.getElementById('canidates').innerHTML = '<strong>List of Canidates:</strong> ' + names;
}
function deleteName() {
var name = document.getElementById('delname').value;
try {
names.remove(name);
update();
} catch {
alert('Not a valid name');
}
}
update();
I need help sorting through some data.
Say I type "piz" in a searchfield. I get in return and array with all the entries that contain "piz".
I now want to display them in the following order:
pizza
pizzeria
apizzetto
berpizzo
First the items that start with what I typed in alphabetical order then the ones that contain what I typed in alphabetical order.
Instead if I sort them alphabetically I get the following
apizzetto
berpizzo
pizza
pizzeria
Does anyone know how to do this?
Thanks for your help.
You can split the data into two arrays, one that starts with your input and one that doesn't. Sort each separately, then combine the two results:
var data = [
'pizzeria',
'berpizzo',
'apizzetto',
'pizza'
];
function sortInputFirst(input, data) {
var first = [];
var others = [];
for (var i = 0; i < data.length; i++) {
if (data[i].indexOf(input) == 0) {
first.push(data[i]);
} else {
others.push(data[i]);
}
}
first.sort();
others.sort();
return(first.concat(others));
}
var results = sortInputFirst('piz', data);
You can see it work here: http://jsfiddle.net/jfriend00/nH2Ff/
The right full solution is:
var data = [
'pizzeria',
'berpizzo',
'apizzetto',
'pizza'
];
var _sortByTerm = function (data, term) {
return data.sort(function (a, b) {
return a.indexOf(term) < b.indexOf(term) ? -1 : 1;
});
};
var result = _sortByTerm(data, 'piz');
If you want object sort, use this function:
var _sortByTerm = function (data, key, term) {
return data.sort(function (a, b) {
return a[key].indexOf(term) < b[key].indexOf(term) ? -1 : 1;
});
};
Using reduce:
const data = ['pizzeria', 'berpizzo', 'pizza', 'apizzetto'];
function sortInputFirst(input, data) {
data.sort();
const [first, others] = data.reduce(([a, b], c) => (c.indexOf(input) == 0 ? [[...a, c], b] : [a, [...b, c]]), [[], []]);
return(first.concat(others));
}
const output = sortInputFirst('piz', data);
console.log(output)
Here's another one:
var str = 'piz';
var arr = ['apizzetto','pizzeria','berpizzo','pizza'];
arr.sort(function(a,b) {
var bgnA = a.substr(0,str.length).toLowerCase();
var bgnB = b.substr(0,str.length).toLowerCase();
if (bgnA == str.toLowerCase()) {
if (bgnB != str.toLowerCase()) return -1;
} else if (bgnB == str.toLowerCase()) return 1;
return a < b ? -1 : (a > b ? 1 : 0);
});
console.log(arr);
Here's how I used the top voted answer to make my search function use a normalized set of data. It removes accents before comparing strings and is also case insensitive.
function getAutocompleteNormalizedMatches(userInput, array) {
const normalizedInput = getNormalizedString(userInput);
let normalizedListItem;
let startsWith = [];
let anywhere = [];
for (let i = 0; i < array.length; i++) {
normalizedListItem = getNormalizedString(array[i]);
if (normalizedListItem.indexOf(normalizedInput) === 0) {
startsWith.push(array[i])
} else if (normalizedListItem.includes(normalizedInput)) {
anywhere.push(array[i])
}
}
startsWith.sort();
anywhere.sort();
return startsWith.concat(anywhere);
}
const getNormalizedString = function (str) {
str = str.replace(/\s+/g, " ").trim();
return (str ? removeDiacritics(str.toLowerCase()) : "");
};
To get the removeDiacritics() function, please refer to this link because it takes quite a bit of useless space if you guys don't need it: Remove accents diacritics in a string with JavaScript