Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
How to combine array of strings in all possible ways
Example 1
input
const words = ["foo", "bar"]
Output
["foobar", "barfoo"]
Example 2
input
const words = ["word","good","best"];
Output
[
"wordgoodbest",
"wordbestgood",
"bestwordgood",
"bestgoodword",
"goodbestword",
"goodwordbest"
]
And so on if input size increased
function combineWords(words) {
const result = [];
if (words.length === 1) {
return words;
}
for (let i = 0; i < words.length; ++i) {
const word = words[i];
const rest = words.slice(0, i).concat(words.slice(i + 1));
const combinations = combineWords(rest);
for (let j = 0; j < combinations.length; ++j) {
result.push(word + combinations[j]);
}
}
return result;
}
// Example by OP in original question
console.log(combineWords(["word","good","best"]))
// Example by OP in comments
console.log(combineWords(["word", "good", "best", "hi"]))
// permutations are length of input factorial
console.log(combineWords(["word","good","best", "another", "more"]).length)
The function first checks if the array only contains one word. If so, it simply returns the array.
Otherwise, it loops through all the words in the array. For each word, it creates a new array that contains all the other words in the original array, excluding the current word. It then calls the function recursively on this new array, which will return an array of all possible combinations of the words in this new array.
Finally, it loops through all the combinations returned by the recursive call and appends the current word to each one, before adding it to the final array of results.
I don't know how efficient it would be but might get you what you need.
Remove duplicate entries from input array
outer loop n times (total no of elements in input array)
inner loop n-1 times (all elements except current outer loop)
Here's an alternative solution.
This creates a set of nested loops (one for each word in the set) using a recursive function. If within the innermost loop the indexes of all the loops comprise a unique set (no repeated numbers. i.e. 1,2,3,4 or 2,1,4,3.) Then pull each of the words in that order and add them to the results array.
function getCombinations(words){
const results = [];
const indexes = [];
const wordCount = words.length;
function looper(loopNumber){
for(indexes[loopNumber] = 0; indexes[loopNumber] < wordCount; indexes[loopNumber]++){
if(loopNumber < wordCount - 1){
looper(loopNumber + 1);
}
else {
if(indexes.length === new Set(indexes).size){
results.push(indexes.map(index => words[index]).join(''))
}
}
}
}
looper(0);
return results;
}
console.log(getCombinations(['a','b']));
console.log(getCombinations(['a','b','c']));
console.log(getCombinations(['a','b','c','d']));
console.log(getCombinations(["word","good","best"]));
Related
This question already has answers here:
Natural sort of alphanumerical strings in JavaScript
(6 answers)
Javascript sort on on part of string
(4 answers)
Closed 7 months ago.
I have an array, I want to position every array element in ascending order but the numbers are found as substrings of the array elements. I sketched the code below to give you an idea of what I am trying to achieve(it works but its ugly). What is the best way to position every element inside an array in ascending order when the numbers are found as substrings inside the array elements. Thanks in advance.
Take a look at my code to better understand my question!
//this works but is uglyyyyy
const myArray = ['test4.js', 'test3.js', 'test1.js', 'test2.js']
let tempArr = []
for (var i = 0; i < myArray.length; i++) {
tempArr.push(myArray[i].replace('test', '').replace('.js', ''))
}
const sortedTempArr = tempArr.sort()
let sortedArray = []
for (var i = 0; i < sortedTempArr.length; i++) {
for (var j = 0; j < myArray.length; j++) {
if (myArray[j].includes(sortedTempArr[i])) {
sortedArray.push(myArray[j])
}
}
}
console.log(sortedArray)
Yes that was ugly ;)
Sort takes a function
For descending, switch a and b
I am assuming only ONE number in the string. The regex will produce a wrong result if you have test2version1.js for example
//this works and is pretty
const myArray = ['test4.js', 'test3.js', 'test11.js', 'test1.js', 'test.js', 'test2.js'];
const re = /\D+/g; // anything not a number
const sortedArray = myArray
.slice(0) // shallow copy
.sort((a, b) => a.replace(re, "") - b.replace(re, ""));
console.log(sortedArray);
.sort() the .match(/\d+/)[0] number of each string (coerced into a number). The bracket notation ([0]) ensures that only the first match is used and everything else is ignored.
const array = ['test4.js','test11.js', 'test3.js', 'test1.js', 'test2.js'];
let result = array.sort((a, b) => +a.match(/\d+/)[0] - b.match(/\d+/)[0]);
console.log(result);
This question already has answers here:
Split array into chunks
(73 answers)
Closed 1 year ago.
I have the js code below:
let splits = 23;
let outer_bound_value = 0;
let data = //this is an array of a large number of predefined objects (10,200+)
for (i = 0; i < data.length; i = i + outer_bound_value) {
outer_bound_value = data.length / splits;
let split_arr = array.slice(i, i + outer_bound_value);
}
The desired outcome of this code is to be able to split the mega array into smaller arrays based on what the value of splits is (if splits is 5, split the large array into 5 sections). I think the approach I have above works but it is dependent on splits being able to be go into the length of the object and it could cause outofbounds errors. Anyone have a more efficient way to do what I am trying to do?
First divide the array by the amount of splits you want.
Normally I would use a new Set() as it is much faster than splitting arrays with slice however I have no idea what type of data you have in your arrays, Sets are unique when it comes to ints.
we use recursion and destructuring to return the sliced array. this will return you multiple arrays into the array length/splits.
const splits = 23;
const data = new Array(10000);
const chunkValue = Math.floor(data.length/splits);
function chunkArray(array, size) {
if(array.length <= size){
return [array]
}
return [array.slice(0,size), ...chunkArray(array.slice(size), size)]
}
const newArrays = chunkArray(data, chunkValue)
I'm posting this question because I am trying to make a function that allows someone to create a multi-dim array. So, the user inputs an array of numbers which are the dimensions of the array (e.g entering [2, 4, 3] would output a 2x4x3 multi-dim array)
I have spent a couple of hours trying to imagine an algorithm that can do this in JS and I came up with this:
Note: I use Node.js v9.11.1
function generate(dimensions) {
// SA = sub-array (I will use this several times here)
// This array will store every SAs of the multi-dim array
// E.g for a 2x4x3 array, it will store a 2-item array, a 4-item array and a 3-item array
var arrays = []
// This fills `arrays` with the SAs
for (var i = 0; i < dimensions.length; i++) arrays.push(new Array(dimensions[i]).slice(0))
// Here it gets a bit complex (at least for me!)
// So what we do is that for each SA (except last), we fill it with copies of the current+1 SA
// So the SA at index 1 will be filled with copies of the array at index 2
// And the array at index 0 will be filled with arrays of index 1 (which was already filled because our for loop starts from the end)
// The array at index 0 is our final multi-dim array
// Goes from the before last SA to the first
for (var current = dimensions.length-2; current !== -1; current--) {
// Fills the current SA with index+1 SA
for (var i = 0; i < arrays[current].length; i++) arrays[current][i] = arrays[current+1].slice(0)
}
// Returns first array, the complete one
return arrays[0].slice(0)
}
My problem is that even if the array is well generated, some SA are passed by reference and not by value so when I do
my_array = generate([2, 4, 3])
my_array[1][2][1] = "hi!" // Fill a random place with "hi!"
Then when I do console.log(my_array), some other cases of the multi-dim array are filled with the same value.
This means that somewhere, an array is passed by reference rather than passed by value which is strange
because I checked the code multiple times and I don't find where this could come from (I use the Array.slice()
method to "copy" the array)
Have I missed something huge?
Your help would be rather appreciated!
To be honest, not sure how your trying to create your mult-dim array,..
But the first thing that springs to mind when seeing something like this, is recursion.
eg..
function generate(dimensions) {
if (!dimensions.length) throw new Error("no dims?");
const dimsize = dimensions[0];
if (dimensions.length === 1) {
return new Array(dimsize).fill(null);
}
const ret = [];
const subdims = dimensions.slice(1);
for (let l = 0; l < dimsize; l+= 1)
ret.push(generate(subdims));
return ret;
}
const my_array = generate([2, 4, 3])
my_array[1][2][1] = "hi!"
console.log(my_array);
I come up with this:
function generate(dims) {
if(dims.length > 0) {
let array = new Array(dims[0]).fill(0);
let childDims = dims.slice();
childDims.shift();
return array.map((el) => {
return generate(childDims);
});
} else return 0;
}
let foo = generate([2, 3, 2]);
foo[0][0][1] = 'hmmmm';
console.log(foo);
Also using recursion to create multidimensional array. But when creating arrays as You saw, have to be carefull about not passing references but real copies of arrays. Slice() will give You only shallow copy.
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
This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 8 years ago.
var data = localStorage.getItem('oldData').split(" ");
I am accessing localStorage as above and getting an array of values. Some of the elements are repeated in the string value for oldData, for example:
apples oranges apples apples
I want data to have only two elements apples and oranges. How can I do this in Javascript?
Array.prototype.unique = function(){
return Object.keys(this.reduce(function(r,v){
return r[v]=1,r;
},{}));
}
Strap it on. It's O(n) because using an object just requires you to loop through the array once and assign every value in it as a key, overwriting as you go. This only works when the values are primitives (or you have Harmony WeakMaps). But that's almost always the kind of array you want to do this one so it works out.
For bonus points here's the second best way to do it. This is at minimum twice as fast as the normal double loop answers and is at minimum as good as the ones requiring presorting,
(but still worse than the above hash method which is infinitely faster).
Array.prototype.unique = function(){
return this.filter(function(s, i, a){
return i == a.lastIndexOf(s);
});
}
The reason it beats every other answer aside from the hash is because it's able to get the benefit of sorting without doing the sorting step. It only searches from the current item forward, and from the other end in reverse, so there will never be a case where two items are checked against each other twice, and there will never be an unnecessary comparison done because it always quits at the very minimum amount of work needed to make a final decision. And it does all of this with the minimum possible creation of placeholder variables as a bonus.
first is to insert one value in your array by using push
var array = [];
array.push("newvalue");
then the next insertion of value, check if your value is existing in your array using "for loop". then if the value does not exist, insert that value using push() again
Array.prototype.unique = function()
{
var a = [];
var l = this.length;
for(var i=0; i<l; i++)
{
for(var j=i+1; j<l; j++)
{ if (this[i] === this[j]) j = ++i; }
a.push(this[i]);
}
return a;
};
Something like this should do the trick:
uniqueValues = function(array) {
var i, value,
l = array.length
set = {},
copy = [];
for (i=0; i<l; ++i) {
set[array[i]] = true;
}
for (value in set) {
if (set.hasOwnProperty(value)) {
copy.push(value);
}
}
return copy;
}
This is what I have used finally
var data = localStorage.getItem('oldData').split(" ");
var sdata = data.sort();
var udata = [];
var j = 0;
udata.push(sdata[0]);
for (var i = 1; i < data.length - 1; i += 1) {
if (sdata[i] != udata[j]) {
udata.push(sdata[i]);
j++;
}
}