I am trying to find an odd string from an given array.
Code :
const friendArray = ["agdum", "bagdum", "chagdum", "lagdum", "jagdum", "magdum"];
function oddFriend(friendArray) {
for (let i = 0; i < friendArray.length; i++) {
if (friendArray[i].length % 2 != 0) {
return friendArray[i];
}
}
}
const myFriend = oddFriend(friendArray);
console.log(myFriend);
You can apply this:
const friendArray = ["agdum","bagdum","chagdum","lagdum","jagdum","magdum",];
function oddFriend(friendArray) {
if (friendArray.length % 2 != 0) {
return friendArray;
}
}
const myFriend = friendArray.filter(oddFriend);
console.log(myFriend);
.flatMap() and a ternary callback makes a simple and readable filter. It's not entirely clear if you wanted only odd or odd and even so there's both versions.
Odd length strings
const fArray = ["agdum", "bagdum", "chagdum", "lagdum", "jagdum", "magdum"];
let odd = fArray.flatMap(o => o.length % 2 === 1 ? [o] : []);
console.log(odd);
Odd & even length strings
const fArray = ["agdum", "bagdum", "chagdum", "lagdum", "jagdum", "magdum"];
let oe = [[], []];
fArray.forEach(o => o.length % 2 === 1 ? oe[0].push(o) : oe[1].push(o));
console.log(oe);
You can use Array.filter() method which will create a new array with all odd friends that pass the test implemented by the provided function.
// Input array
const friendArray = ["agdum", "bagdum", "chagdum", "lagdum", "jagdum", "magdum"];
// Filtered result
console.log(friendArray.filter((friend) => friend.length % 2 !== 0));
Related
I asked myself If there was a way to solve the problem of counting duplicated numbers just iterating once and also using the reduce method.
This is what I got:
const countDuplicate = (numbers) => {
const occurrencies = {};
for (var k = 0; k < numbers.length; k++) {
occurrencies[numbers[k]] = isNaN(occurrencies[numbers[k]])
? 1
: occurrencies[numbers[k]] + 1;
}
const counter = Object.values(occurrencies).reduce(
(total, each) => total + (each > 1 ? 1 : 0),
0
);
return counter;
};
countDuplicate([1,2,3,4]); // returns 0
countDuplicate([1,2,3,4,1,2,2]); // returns 2
It can definitely be done in one pass - your accumulator can be an object, storing seen numbers quantity in one property and number of seen duplicates in another. So, when the minimum dup requirement is met (number is seen exactly twice), you get the dups quantity increased (further occurrences of this number will be simply ignored) :
const src = [1,2,3,4,1,2,2],
{countDups} = src.reduce((r, n) => {
r.countN[n] = (r.countN[n]||0)+1
r.countN[n] == 2 && r.countDups++
return r
}, {countN:{}, countDups: 0})
console.log(countDups)
Question 2: The input consist of a string, "o" represents odd number, "e" represents even number to be printed
Example 1.
Input: 8-e
Expected Output: 2|4|6|8
Example 2.
Input: 6-o
Expected Output: 1|3|5
Example 3.
Input: 1-o
Expected Output: 1
if have tried with for loop, but I'am a beginner so I'am confused with(-e)
const evenOdd = (number) => {
let evenvalue = [];
let oddValue=[];
for(let i =0; i<=number; i++){
if(number%i==0)
evenvalue.push(i);
console.log(evenvalue);
}if(number%i!=0){
oddValue.push(i);
console.log(oddValue);
}
};
evenOdd(9);
You could take a while statement and get a start value of one plus an offset of one if the wanted type is even. Then iterate and add the value to the result set until the value is greater than the maximum value.
function fn(request) {
var [max, type] = request.split('-'),
i = 1 + (type === 'e'),
result = [];
while (i <= max) {
result.push(i);
i += 2;
}
return result;
}
console.log(...fn('8-e'));
console.log(...fn('6-o'));
console.log(...fn('1-o'));
You will need to extract the letter and the number from you string first. One easy way to do that :
const evenOdd = (s) => {
let odd = s.length-1 ==='o';
let number = Number(s.substring(0, s.length-2));
let evenvalue = [];
...
if(odd){...} else {...}
};
You could also use split() or if the pattern was more complicated, a Regex.
You can split on - and add based on type add values upto the number
Split the given input by -, first value represents max number and second represents it's type
Check the type if it is even add the even values start from 2 and upto to the max number else start from 1, and join them with | in the end
let func = (input) => {
let [num, type] = input.split('-')
let arr = []
let i = 1 + (type === 'e')
while (i <= num) {
arr.push(i)
i += 2
}
return arr.join('|')
}
console.log(func('8-e'))
console.log(func('1-o'))
console.log(func('6-o'))
Basically, don't supply a number to the function, supply a string and then parse the string. That is, don't try and give the function 9-e, give it '9-e'.
Get the parts of the input by splitting on -.
Turn the number into a number.
Give 0 for even, 1 for odd (x % 2 is 0 for even number, 1 for odd).
Build the results.
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
let result = [];
for(let i = 1; i <= number; i++)
{
if(i%2 === numberType)
{
result.push(i);
}
}
return result;
}
console.log(listNumbers('8-e'));
Or if you want make the code look clever:
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
return Array.from(Array(number), (x,i) => i + 1 ).filter(x => x%2 == numberType);
}
console.log(listNumbers('8-e'));
What I'm trying to achieve is to create a formatted number with thousands-delimiter from a simple string input.
So my input would look something like let input = "12345" and my expected return value should look like "12,345".
I know there are already several libraries, which take care of this, but I want to keep it simple and just do it by myself. My current solution is a bit redundant (because of the double .reverse()) and I'm pretty sure, that there is a better solution.
let array = input.split('');
array.reverse();
for (let i = 3; i < array.length; i += 4) {
array.splice(i, 0, ',');
}
array.reverse();
return array.join('');
I have made a similar answer for another question: Insert new element after each nt-h array elements. It is a generalized method that insert a token every N positions. The solution uses a while loop with the Array.splice() method. To meet your request, I have extended it to support start the inserts from the end of the array. Just another option...
let insertTokenEveryN = (arr, token, n, fromEnd) => {
// Clone the received array, so we don't mutate the
// original one. You can ignore this if you don't mind.
let a = arr.slice(0);
// Insert the <token> every <n> elements.
let idx = fromEnd ? a.length - n : n;
while ((fromEnd ? idx >= 1 : idx <= a.length))
{
a.splice(idx, 0, token);
idx = (fromEnd ? idx - n : idx + n + 1);
}
return a;
};
let array = Array.from("1234567890");
let res1 = insertTokenEveryN(array, ",", 3, true);
console.log(res1.join(""));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
But, obviously, like people commented, your best option for this will be using input.toLocaleString('en-US'):
let input = "1234567890";
console.log(Number(input).toLocaleString("en-US"));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Although in your example the you finish with a string, the title says "into array". This is quite a compact way using lodash:
import { chunk, flatten } from 'lodash'
const ADD_EVERY = 5
const ITEM_TO_ADD = {}
const data = flatten(
chunk(input, ADD_EVERY).map((section) =>
section.length === ADD_EVERY ? [...section, ITEM_TO_ADD] : section
)
It is conceptually kind of similar to doing a split().join()
Here is a plain soluce but regex is better.
function separate(str, separator) {
// Handling the head case (from 0 to 2 size)
const headSize = str.length % 3;
let newFormat = headSize ? `${str.substr(0, headSize)}${separator}` : '';
// Handle every 3 character
const nbTripleChar = (str.length - headSize) / 3;
for (let i = 0; i < nbTripleChar; i += 1) {
newFormat = `${newFormat}${str.substr((i * 3) + headSize, 3)}`;
if ((i + 1) !== nbTripleChar) {
newFormat = `${newFormat}${separator}`;
}
}
return newFormat;
}
console.log(separate('12515', ','));
You can iterate backwards through the array and build the string using a second index.
The string concatenation might be costly but it only iterates the list once. You could also probably us .reduce() to do that without a for loop(since almost any array-iteration operation can be done as a function call these days);
let input = 123456789949949291;
let array = input.toString().split('');
let candidateString = '';
for (let i = array.length-1; i >=0; i--) {
candidateString=array[i]+candidateString;
let revIndex=array.length-i;
if(revIndex%3==0 && revIndex!== array.length){
candidateString = ','+candidateString;
}
}
console.log(candidateString);
You could replace by looking for a group of three characters to the end of the string.
var string = '12345678';
console.log(string.replace(/(?=(...)+$)/g, ','));
If you are not a fan of Regex. or builtins like toLocaleString() this should handle most cases you might encounter
function format(str) {
str = str.trim().replace(/\s+/g, '')
if (isNaN(str)) return 'NaN'
str = str.split('')
let strBuild = [str.pop()]
for (let number of strBuild) {
if (strBuild.length % 3 === 0) strBuild.unshift(str.pop() + ',')
else strBuild.unshift(str.pop())
if (!str.length) return strBuild.join('');
}
}
console.log(format('1 '))
console.log(format('1 a 2'))
console.log(format(' 12 '))
console.log(format('123 '))
console.log(format(' 123'))
console.log(format(' 1 2 3'))
console.log(format('1 2 3 '))
console.log(format('12 34'))
console.log(format('123 45678'))
console.log(format('12349 567 8'))
console.log(format(' 1234 9567 81 '))
console.log(format(' 1234 9567 81 9 7 5 6 4 5 8 '))
console.log(format(' 1234 9567 81 c '))
I have built a function that allows you to pass through an array and it successfully returns the second highest and second lowest numbers. However, I'm new to error handling and don't understand why this fails:
getNos([5,"5",8]);
It works correctly when passing in getNos([5,5,8]); or passing arrays like getNos(["5",8]);.
Can someone explain what's happening here and how to fix it? Thanks for any help here - the function code is below:
function getNos(arr){
if (!Array.isArray(arr) || arr.length == 0 || arr.length == 1 || (arr.every(c => !isNaN(c)) == false)) {
throw 'Invalid Input';
} else {
var result;
var uniqueVals = Array.from(new Set(arr));
var highest = highestVal(arr);
var lowest = lowestVal(arr);
if (uniqueVals.length == 1) {
result = arr[0] + " " + arr[0];
} else if (arr.length == 2 || uniqueVals.length == 2) {
result = highest + " " + lowest;
} else {
arr = arr.filter(item => ((item !== highest) && (item !== lowest)));
var secondHighest = highestVal(arr);
var secondLowest = lowestVal(arr);
if (arr.length == 1) {
arr = arr.slice(arr.indexOf(secondHighest));
result = highestVal(arr);
} else {
result = secondLowest + " " + secondHighest;
}
}
return result;
}
function highestVal(a) { return a.reduce((a, b) => a > b ? a : b ) };
function lowestVal(a) { return a.reduce((a, b) => a < b ? a : b ) };
}
Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?
A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.
To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.
let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.
Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set
Change
var uniqueVals = Array.from(new Set(arr));
To
var uniqueVals = Array.from(new Set(arr.map(Number)));
The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".
When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).
Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?
In the case of filter for valid numbers. Filter the input as follows...
arr = arr.filter(data => typeof data === 'number')
In the case of converting values to a number and removing those that cannot be converted...
arr = arr.reduce(((acc, el) => {
const num = Number(el);
if (!Number.isNaN(num)) acc.push(num);
return acc;
}), []);
So I'm making this ReactJS application.
Part of a filtering system I have the following problem:
Simplified...
I have an array, let's say its simple one like let arr = [1,7,4,3,4,7];
and I also input an N variable from the user that is a simple integer input.
I need to return or console.log() the integers from the array that is repeated N times. If there is nonsuch repeating number log err msg or return -1;
For instance,
let arr = [1,7,4,3,4,7]; and let n = 2; i get 7- cos 7 repeats 2 times
let arr = [7,4,5,3,5,5,3,4,3,2,1]; and let n = 3; i get 5 - cos 5 repeats 3 times
let arr = [1,6,4,6,4,6]; and let n = 4; i get -1 or cl("err") - cos nothing repeats 4 times
Code from comments:
const getRepeatingNumber = (arr, n) => {
for (unit of arr) {
if (unit === maj_unit) count++;
else {
count--;
if (count === 0) {
maj_unit = unit;
count = 1;
}
}
}
return maj_unit;
}
You can use array#every, create an accumulator and place the number as key and its frequency as value, once the value reaches the specified number of occurrence, break from the loop using return false, then return the result.
const getRepeatingNumber = (arr, count) => {
let result = -1, hash = {};
arr.every(n => {
hash[n] = (hash[n] || 0) + 1;
if(hash[n] === count) {
result = n;
return false;
}
return true;
});
return result;
}
console.log(getRepeatingNumber([1,7,4,3,4,7],2));
console.log(getRepeatingNumber([7,4,5,3,5,5,3,4,3,2,1], 3));
console.log(getRepeatingNumber([1,6,4,6,4,6], 4));
Below is the code which will fix your problem I hope.
You need to loop over all array values and find how many time each value occurred and save number of occurrence in a result array because there may be multiple values occurred n number of times. i.e. in your provided array let arr = [1,7,4,3,4,7]; 7 and 4 occurred twice but i am returning result[0] since you might only need first occurred value for n times.
let arr = [1,7,4,3,4,7];
let getRepeatingNumber = function (arr, n) {
let result = [];
arr.forEach((value) => {
if (arr.filter(val => val === value).length === n && !result.includes(value)) {
result.push(value);
}
});
return result.length ? result[0] : -1
}
console.log(getRepeatingNumber(arr, 2)); // 7