I have a method which I have put on the array prototype that reverses the array (this is done for learning purposes only). This method should reverse the array in place.
Array.prototype.yarra = function () {
for (let left=0, right=this.length-1; left<right; left++, right--) {
[this[left], this[right]] = [this[right], this[left]]
}
return this
};
I have written some tests to check if the method works as expected.
describe('yarra', function () {
it('should reverse an array in place and return it', function () {
var arr = [1,2,3];
var reversedArr = arr.yarra();
reversedArr.should.eql([3,2,1]);
arr.should.equal.reversedArr;
[4,5,6].yarra().should.eql([6,5,4]);
});
});
I realise the tests don't work as expected as I reversed the array out of place and returned a new array, and it still passed. Also, because var reversedArr = arr.yarra() means arr will always equal reversedArr, so it doesn't really check for anything.
How would I write a test that can check if the array is reversed in place?
const assert = require('assert');
Array.prototype.yarra = function () {
for (let left=0, right=this.length-1; left<right; left++, right--) {
[this[left], this[right]] = [this[right], this[left]]
}
return this
};
describe('yarra1', () => {
it('should reverse an array in place and return it', () => {
let arr = [1,2,3];
let rev = [3,2,1];
let reversedArr = arr.yarra();
for(let i =0;i<arr.length;i++){
assert(reversedArr[i]===rev[i])
}
});
});
describe('yarra2', () => {
it('should reverse an array in place and return it', () => {
let arr = [1,2,3];
let rev = [3,2,1];
let reversedArr = arr.yarra();
assert(reversedArr.toString() === rev.toString())
});
});
Related
Context
I have a function that passes out a Map of ints, and an unrelated int. Here's an example that does work:
const myFunction = () => {
let color_map = new Map();
color_map.set(111, 222);
color_map.set(333, 444);
color_map.set(555, 666);
let rando = 777;
return {color_map, rando};
}
const {color_map, rando} = myFunction();
console.log("Results:", color_map, rando)
My Code
My actual code is very similar:
const makeColorMap = (img) => {
let color_map = new Map();
let psize = 0;
// ...
return {color_map, psize};
}
// makeColorMap() is passed in as 'method'
const {color_map, psize} = method(arr);
However, when I run this, both come out as undefined.
Does this have to do with the anonymous function or something? I'm really lost.
Maybe related, but in a previous iteration, the first two elements of the Map were being put into color_map and psize, respectively. What gives?
Your code works, but you are not calling makeColorMap, instead you call some method:
const makeColorMap = (img) => {
let color_map = new Map();
let psize = 0;
// ...
return {
color_map,
psize
};
}
const arr = [];
const method = makeColorMap;
const {color_map, psize} = method(arr);
console.log(color_map, psize);
What you need to do in your app is to make sure that method is indeed a makeColorMap, which is probably not the case in your app
I get data from the database of which I only need two arrays. Using two variables, I get the result I need, but I understand, that this code is not written correctly. Even npm writes that the arrow function should return something, so I added "return false";
let flagUrls = [];
let countryNames = [];
country.map((country, index) => {
flagUrls[index] = country.flagUrls;
countryNames[index] = country.countryNames;
return false;
});
this.setState({ flagUrls, countryNames });
I tried like this:
let flagsAndCountrys = country.map((country, index) =>[country.flagUrls, country.countryNames])
this.setState({
flagsAndCountrys.flagUrls,
flagsAndCountrys.countryNames
});
mapmethod creates a new array with the return value of the provided function on every element in the calling array.
Notice the word return in the above line. You need to return something that will be inserted in the new array.
So, using map you can create a new array, consisting of objects with only the flagUrls and countryNames field like so:
let result = country.map((country, index) => {
return {
flagUrl: country.flagUrls,
countryName: country.countryNames
}
});
If you want maintain two array of flagUrls and countryNames, you should not be using map. It's better to use forEach here, like so:
let flagUrls = [];
let countryNames = [];
country.forEach((country, index) => {
flagUrls.push(country.flagUrls);
countryNames.push(country.countryNames);
});
Using destructuring for this, replace the first parameter passed to the provided function country with the values like: {flagUrls, countryNames}
country.forEach(({flagUrls, countryNames}, index) => {
flagUrls.push(flagUrls);
countryNames.push(countryNames);
});
The proper way to create two arrays would be to call map twice:
const flagUrls = countries.map(country => country.flagUrl);
const countryNames = countries.map(country => country.countryName);
If you want to do it with only a single iteration, then you'll have to use a loop with side effects - similar to the map call you did, but you'd rather use forEach:
let flagUrls = [];
let countryNames = [];
countries.forEach((country, index) => {
flagUrls[index] = country.flagUrl;
countryNames[index] = country.countryName;
});
or just
let flagUrls = [];
let countryNames = [];
for (const country of countries) {
flagUrls.push(country.flagUrl);
countryNames.push(country.countryName);
}
I’m trying to create a simple loop of animation functions. I've stored their names in an array and am able to log out each object as a string with a click event. However I can't seem to call the corresponding functions of that event
I've tried to do this but I get an error nt[rt] is not a function
arrAnimations[activeScene]()
I've tried many approaches from stack overflow from similar questions, such as creating a helper function like this
myFunction = function(){};
var arrAnimations = {italy: myFunction};
arrAnimations['activeScene']();//executes the function
and this
var tmp = arrAnimations[activeScene]
window[tmp]
Here is the code:
var arrAnimations = [
'italy',
'czech',
'russia'
]
var activeScene = 0;
document.getElementById('animate').addEventListener("click",
function incNumber() {
if (activeScene < arrAnimations.length - 1) {
activeScene++;
} else if (activeScene = arrAnimations.length - 1) {
activeScene = 0;
}
// console.log(arrAnimations[activeScene])
}
)
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
<div id="animate">Animate</div>
The array can store the actual functions themselves, instead of the function names.
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
var arrAnimations = [ italy, czech, russia ]
Then locate the item in the array, and call it:
var activeScene = 0;
arrAnimations[activeScene]()
Demo in Stack Snippets
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
var arrAnimations = [ italy, czech, russia ]
var index = 0;
function callNextFunction() {
index = index >= arrAnimations.length - 1 ? 0 : index + 1
arrAnimations[index]()
}
var btn = document.getElementById('animate')
btn.addEventListener("click", callNextFunction)
<button id="animate">Animate</button>
In your commented out line:
console.log(arrAnimations[activeScene])
You're trying to call a method on the array, which doesn't exist. It's an array of strings. Instead, you need to get the string value, then use that to call a method on the window.
window[arrAnimations[activeScene]]();
With that said though, I'd make your code a bit simpler and use lambda functions, and avoid a couple of if statements, try this:
<div id="animate">Animate</div>
<script>
var arrAnimations = [
() => console.log('italy'),
() => console.log('czech'),
() => console.log('russia')
]
var activeScene = 0;
document.getElementById('animate').addEventListener('click', () => {
arrAnimations[activeScene]();
activeScene++;
activeScene = activeScene % arrAnimations.length;
});
</script>
italy = () => console.log('italy')
czech = () => console.log('czech')
russia = () => console.log('russia')
if Array of functions:
let arrAnimationsAsFunctions = [ italy , czech , russia];
arrAnimationsAsFunctions.forEach(animation => animation())
if Array of Strings:
let arrAnimationsAsStrings = [ 'italy' , 'czech' , 'russia' ];
arrAnimationsAsStrings.forEach(animation => eval(animation)())
use eval to run a string as JS code
Is this what you want?
foo = () => console.log('foo')
bar = () => console.log('bar')
baz = () => console.log('baz')
fns = {
foo,
bar,
baz
}
Object.keys(fns).forEach(fn => fns[fn]())
fns['foo']()
fns['bar']()
Note: you can't cast a string to a function like this, at least in Javascript:
let fn = () => {}
let foo = 'fn'
foo() // X
// foo is a string, not a function, It is just a coincidence that the content of the string is same with the function's name
I trying to show a message in an array is empty in a filter method in Vue.
However, it seems my computed function still returns an array of empty object (If I search for something not there)
What I wish is that it only returns the object that actually has a value - the empty ones should be filtered out?
So if I search for "fjhdsfjsdfjsd" ex, it still return about 200 items, just empty objects, which it shouldnt?
The computed function looks like:
filteredAlarms: function () {
let filter = {};
let searchString = this.search_string.toLowerCase();
Object.keys(this.eventLog).forEach(key => {
filter[key] = this.eventLog[key].filter(item => {
let systemName = item.system_name.toLowerCase();
if(item.type.includes("alarm") && systemName.includes(searchString)) {
return item;
}
});
});
return filter
},
Array.prototype.filter must return a boolean. Just remove the if and the return item part and just return your if condition:
filteredAlarms: function () {
let searchString = this.search_string.toLowerCase();
let eventKeys = Object.keys(this.eventLog);
return eventKeys.reduce((filter, key) => {
let items = this.eventLog[key].filter(item => {
let systemName = item.system_name.toLowerCase();
return item.type.includes("alarm") && systemName.includes(searchString);
});
return Object.assign(filter, { [key]: items });
}, {});
}
Try this one. I hope this will work.
filteredAlarms: function () {
let filter = {};
let searchString = this.search_string.toLowerCase();
Object.keys(this.eventLog).forEach(key => {
filter[key] = this.eventLog[key].filter(function(item){
return item.type.includes("alarm") && item.system_name.toLowerCase().includes(searchString);
});
});
return filter
},
I have some code like:
var filteredData = [];
asyncFunc().done(function () {
filteredData = blablabla...
});
return filteredData;
This is a project to deliver soon. I cannot change it to callback or $.Deffered due to the existing code/design.
Is it possible to force it to wait until aysncFunc have done its jobs and then return the real filteredData that I want?
EDIT:
#MerynStol you're right. Async was sent to last of the job queue(I forgot the term), which is after while and return. So when while ends, return execute immediately.
Should I keep on this or try to bargain more time for a re-structure?
You could extend the Function prototype:
Function.prototype.and = Function.prototype.and || function(fn){
this();
var args = [].slice.call(arguments), arg;
while (args.length) {
arg = args.shift();
if (arg instanceof Function) {
arg();
}
}
}
and use it with a comma operator like this:
var filteredData = [];
return (asyncFunc.and( function () {
filteredData = /* do stuff */
} ), filteredData);
Or if method done works as expected just use:
var filteredData = [];
return (asyncFunc().done(function () {
filteredData = /*blablabla...*/
}), filteredData);