Random select array with remove items (jQuery) - javascript

I am trying to find a way to get values from an array of random way without repeating them, I found the following solution:
var letters = ["A", "B", "C"];
var getRandom = (function(array) {
var notGivenItems = array.map(function(el) {
return el;
});
var getIndex = function() {
return Math.floor(Math.random() * notGivenItems.length);
};
return function() {
if (notGivenItems.length === 0) {
return;
}
return notGivenItems.splice(getIndex(), 1)[0];
};
})(letters);
console.log(getRandom());
console.log(getRandom());
console.log(getRandom());
console.log(getRandom());
If I print the console.log() 4 times, at last, the array appears as undefined, and that's precisely what I need. However, I need (function () {... don't be fired automatically, because the value that comes via AJAX. So, should be something like:
function selec() {
var getRandom = (function(array) {
var notGivenItems = array.map(function(el) {
return el;
});
var getIndex = function() {
return Math.floor(Math.random() * notGivenItems.length);
};
return function() {
if (notGivenItems.length === 0) {
return;
}
return notGivenItems.splice(getIndex(), 1)[0];
};
})(letters);
return getRandom();
}
console.log(selec());
But then, the function continues printing values continuously, without return undefined.

I hope I have understood your problem.. if yes, was really easy. Check this fiddle
var letters = ["A", "B", "C"];
function getRandom(array){
var notGivenItems = array.map(function(el){
return el;
});
var getIndex=function(){
return Math.floor(Math.random() * notGivenItems.length)
};
if (notGivenItems.length === 0)
return;
return array.splice(getIndex(), 1)[0];
}
console.log(getRandom(letters));
console.log(getRandom(letters));
console.log(getRandom(letters));
console.log(getRandom(letters));

What's happening is that every time you call selec(), it is re-creating the getRandom function.
What you need to do is define getRandom outside of the selec() function scope.
You can do it at the same level:
var getRandom = (function(array) { ... })(letters);
var selec = function() { return getRandom; };
or you can create a closure to protect getRandom from naming conflicts:
var selec = (function() {
var getRandom = (function(array) { ... })(letters);
return function() { return getRandom; };
})();

Related

JS function to generate unique random number

I have the following utility function:
var Utilities = (function (array, maxN) {
function generateRandomNumber(array, maxN) {
let randomN = Math.floor(Math.random() * (maxN - 0) + 0);
if(array.length == maxN) {
array = [];
}
if(!array.includes(randomN)) {
array.push(randomN);
}
else {
randomN = generateRandomNumber(array, maxN);
}
return randomN;
}
return {
generateRandomNumber: generateRandomNumber
};
})();
export default Utilities;
which I am using like so:
function getRandomNumber() {
var array = [];
let randomN = Utilities.generateRandomNumber(array, 5);
return randomN;
}
I am then using this function inside a react component like so:
...
getNewQuestion = () => {
var randomN = getRandomNumber();
console.log(randomN);
this.setState({
question: this.state.data.data.questions[randomN]
})
this.setCatBgColor(this.state.data.data.questions[randomN].category);
}
...
I have just made a test and I got:
0,0,3
which is wrong as they should be unique until the length of 5 (in this case) is reached.
Your function
function getRandomNumber() {
var array = [];
let randomN = Utilities.generateRandomNumber(array, 5);
return randomN;
}
does create a new empty array on every call, not remembering anything. generateRandomNumber won't know about the previous invocations. Put the variable declaration and initialisation outside of the function:
var array = [];
function getRandomNumber() {
return Utilities.generateRandomNumber(array, 5);
}

How to implement a general set randomizer?

Let us suppose that I intend to implement a randomization functionality, like this:
function Randomizer() {
//Get random member name of object
Object.prototype.getRandomKey = function() {
var keys = Object.keys(this);
return keys[Math.floor(Math.random() * keys.length)];
};
//Get random member value of object
Object.prototype.getRandomElement = function() {
return this[this.getRandomKey()];
};
//Get random index of array
Array.prototype.getRandomKey = function() {
return Math.floor(Math.random() * this.length);
};
//Get random element of array
Array.prototype.getRandomElement = function() {
return this[this.getRandomKey()];
};
//Get random return key of function result
Function.prototype.getRandomKey = function() {
var result = this.apply(this, arguments);
return result && result.getRandomKey();
};
//Get random return member of function result
Function.prototype.getRandomElement = function() {
var result = this.apply(this, arguments);
return result && result.getRandomElement(result.getRandomKey());
};
//Get random element name of what if supported
Randomizer.getRandomKey = function(what) {
if ((!what) || (["undefined", "number", "boolean"].indexOf(typeof what) >= 0)) {
//unsupported
} else if (typeof what !== "function") {
return what.getRandomKey(arguments);
} else {
return Randomizer.getRandomKey(what.apply(this, arguments));
}
};
//Get random element value of what if supported
Randomizer.getRandomElement = function(what) {
if ((!what) || (["undefined", "number", "boolean"].indexOf(typeof what) >= 0)) {
//unsupported
} else if (typeof what !== "function") {
return what.getRandomElement(arguments);
} else {
return Randomizer.getRandomElement(what.apply(this, arguments));
}
};
}
This is how I initialize it
Randomizer();
Usage example
function lorem(b, a) {
return a.substring(1);
}
Randomizer.getRandomElement(lorem, "abcde");
My question is as follows: How can I modify Randomizer.getRandomKey and Randomizer.getRandomElement so that I can avoid defining a b parameter in lorem which essentially is the lorem object itself at the getRandomElement call? Can I do something with the arguments object before calling apply to get rid of its very first element and pass the arguments after that?
Can I do something with the arguments object before calling apply to get rid of its very first element and pass the arguments after that?
Yes, slice does that:
var slice = Array.prototype.slice;
….apply(this, slice.call(arguments, 1))
An alternative to Array.prototype.slice is using ES6 rest parameters:
Function.prototype.getRandomKey = function(ignoreFirstArg, ...args) {
var result = this.apply(this, args);
// ...
};

Pass vars to other method javascript

I want to pass var "firstWord" with saved value in it from one method to another.
var obj = {
getWords: function () {
var words = [];
$('input').each(function () {
words.push($(this).val());
});
var firstWord = words[0],
secondWord = words[1],
thirdWord = words[2];
},
pushWords: function () {
Array.prototype.insert = function (index, item) {
this.splice(index, 0, item);
};
var fruits = ["Banana", "Orange", "Apple", "Mango"],
randomPosition = (Math.floor(Math.random() * (5 - 2 + 1)) + 1);
fruits.insert(randomPosition, firstWord);
$('body').append(fruits);
}
};
Probably my code is wrong a bit, but is there any possibility to do that in this case?
If you declare a varible with the var keyword, it's a only available in the function. Leave it out and you'll have a global variable, which you can access from other functions as well. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var)
One way it to pass one function's value to the other, like:
function one(){
var var1 = "hello";
two(var1);
}
function two(x){
alert(x);
}
This should print "hello" for you.
The other way is to declare your firstWord as a global variable.
Try to return the array like below,
getWords: function () {
var words = [];
$('input').each(function () {
words.push($(this).val());
});
return words;
},
and in push words
pushWords: function () {
var arr = this.getWords();
................
................
................
fruits.insert(randomPosition, arr[0]);
}
$('body').append(fruits);
since var firstword,secondword and thirdword are only accessible inside the getwords function you must try to return it. And don't forget to validate the
return value before you use it. Hope it helps..
See example here https://jsfiddle.net/xz0ofkjx/
So make it a property of the object.
var obj = {
_words : [],
setWords : function () {
this._words = ["hello","world"];
},
pushWords : function () {
this._words.push("foo");
},
readWords : function () {
console.log(this._words);
}
}
obj.readWords();
obj.setWords();
obj.readWords();
obj.pushWords();
obj.readWords();

Rxjs observing object updates and changes

I am currently trying to observe any changes to a given object including all of it's elements.
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
<script>
var elem = document.getElementById("test1");
var log = function(x) {
elem.innerHTML += x + "<br/><br/><br/>";
};
var a = [{a:1,b:2},
{a:2,b:5}
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x) {
return JSON.stringify(x);
});
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1];
</script>
This code runs and fires correctly.
however. if I instead to this
a[0]['a'] = 3;
Then nothing happens.
EDIT
A better way to phrase this, how can I observe changes from an array of objects?
If you want only the nested object changes:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
})
);
The flatMap or selectMany (they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
http://reactivex.io/documentation/operators/flatmap.html
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
var a = [
{a:1,b:2},
{a:2,b:5}
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x) {
return JSON.stringify(x);
});
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) { return [o, i]; }))
.flatMap(function(oi) {
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x) {
var y = {
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
};
return JSON.stringify(y);
});
})
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1]
a[1]['b'] = 7
Thanks to #electrichead here we're not using concatMap because the sources that we made by ofObjectChanges and ofArrayChanges never complete.
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj) {
if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
return new Rx.AnonymousObservable(function(observer) {
function observerFn(changes) {
for(var i = 0, len = changes.length; i < len; i++) {
observer.onNext(changes[i]);
}
}
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn){
for(var i=0;i<Object.keys(element).length;i++){
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object"){
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
}
}
}
return function () {
Object.unobserve(obj, observerFn);
};
});
};
//Test
var json = {
element : {
name : "Yocto",
job : {
title: "Designer"
}
},
element1: {
name : "Mokto"
}
};
setTimeout(function(){
json.element.job.title = "A Great Designer";
},3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
json.element.name = "Candy Joe";

JavaScript function chaining using the singleton pattern

I have a small piece of code written like in below.
var MY = MY || {};
MY.Farm = (function () {
var add = function(x){
console.log(x)
return this + this;
};
return {
add: function(x){
return add(x);
}
}
});
On a separate file I create sheep an instance of MY.Farm
var sheep = new MY.Farm()
I want to be able to call the function like the following with an output 6
sheep.add(3).add(2).add(1)
Any ideas how I can achieve this? What are the changes required to the MY.Farm snippet to accommodate this?
Thanks in advance.
Something like this
var MY = MY || {};
MY.Farm = (function () {
var x=0;
return {
add: function(newX){
if(typeof(newX) !="undefined") {
x+=newX;
return this;
}
return x;
}
}
});
var sheep = MY.Farm();
console.log( sheep.add(2).add(4).add());
http://jsfiddle.net/7q0143er/
You're not too far off. The trick is you need to keep track of the value somewhere, like in a private variable, and add needs to return this. Finally, you need a way to get the value out when you're done:
MY.Farm = function () {
var total = 0;
return {
add: function(x) {
total += x;
return this;
},
value: function() {
return total;
}
};
};
var sheep = new MY.Farm();
sheep.add(3);
console.log(sheep.value()); // => 3
console.log(sheep.add(1).add(2).value()); // => 6

Categories

Resources