I have a dropdown of country on a webpage. I need to validate the country names in drop down is sorted using Protractor-Cucumber.
I located all options in dropdown using element.all() and used a forEach loop on array. For each iteration, it extract the text and add to another array. Since extracting text takes some time, my resultant array does not have texts in same order as it appears in drop down.
element.all(by.css('ul.sbsb_b')).then(function(allOptions){
allOptions.forEach(function(optn){
optn.getText().then(function(text){
result.push(text);
})
})
});
If my dropdown contains options as A,B,C,D then resultant array should give me in same order. Above logic works fine for less number of options. I want forEach to do iteration one by one instead of all at once because of asynchronous nature.
The method I would attempt for this issue would be to convert your ElementArrayFinder into an array of strings directly using .getText(). I would imagine this would preserve the order but cannot say for sure.
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
console.log(typeof allOptions)
console.log(Array.isArray(allOptions))
}
To preform your validation there are two approaches you could take which do not require any particular order of the state names array you are extracting.
You could sort the array and then expect them both to be equal.
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
expect(allOptions.sort()).toEqual(expectedStates);
}
Or you could validate that the array you have created is the same length as your expected array of states and then verify that every expected state appears at least once in the created array
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
expect(allOptions.length).toBe(expectedStates.length);
for(let i = 0; i < expectedStates.length; count++){
expect(allOptions).toContain(expectedStates[i]);
}
}
I have the the following data being returned by my api.
[{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}]
I want to format it so that the months are all grouped under each category like this:
[{"category":"Amazon","month":{"Jan":9.75,"Feb":9.75,"Mar":9.75,"Apr":9.75,etc...}]
How can I do this with javascript?
What I'm ultimately trying to do is to display some pivoted data in a table. I'm not sure what the best design is to accomplish this.
Right now, I'm just setting up a table dynamically and adding in the data corresponding to each row. Are there better design patterns for doing this?
You can reduce the array of objects to an object using the categories as keys, and adding the months, and then map it back to an array again
var arr = [{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}];
var o = arr.reduce( (a,b) => {
a[b.category] = a[b.category] || [];
a[b.category].push({[b.month]:b.total});
return a;
}, {});
var a = Object.keys(o).map(function(k) {
return {category : k, month : Object.assign.apply({},o[k])};
});
console.log(a);
I would take the following approach:
Write down on a piece of paper how to solve the problem (the "algorithm").
Flesh out this algorithm with more details. Sometimes this is called "pseudo-code".
Convert the pseudo-code into JavaScript.
For instance, your algorithm might look like this:
Create a new thing to hold the results.
Loop through the elements in the input.
For each element in the input, update the results thing.
Return the result.
Sometimes it helps to read out the algorithm aloud to yourself. Or animate the algorithm on a blackboard. Or talk through the algorithm with someone nearby.
The pseudo-code might be:
Create a new array containing a new object to hold the results, with a category property set to "Amazon", and a months property set to an empty object.
Loop through the elements in the input array.
For each element, add a new property to the months property of the results object, whose key is the value of the month property from the element, and whose value is the value of the total property from the element.
Return the result.
If you have specific questions about any of those steps, you can research it further, or ask, such as:
How do I create a new array, with an object inside?
How do I loop through the elements of an array?
How do I retrieve a property from an object?
How do I add a new key/value pair to an object?
How do I return the result?
If you are unfamiliar with any of the terms used above--such as array, object, property, key, value, or element--research them and make sure you know what they mean. Knowing and using correct terminology is the first step to successful programming!
When converting your algorithm into JS, write it step by step, and test it at each phase. For instance, start with a version which doesn't loop over the input at all, and make sure it produces a correct output of [{category: "Amazon", month: {}}]. Walk though your code in the debugger at this and each following step--if you don't know how to use the debugger, learning that should be your first priority! If you want to check a little bit of syntax, to make sure it does what you think, just try it out by typing it into the console. If you don't know what the console is, learning that should be another top priority.
All the above assumes that you've got a single Amazon category. If you are going to have multiple categories, and want multiple objects (one for each) in your output array, then start over from the top and write the algorithm and pseudo-code which can handle that.
Below, I have attached an image with some console output. What I would like to do is, grab all the numbered nodes (so, 0 and 1, but there could be more or less), and put them into an array (like [0, 1]).
Is this possible?
Use .toArray().
var listOfNodes = $list.toArray();
EDIT: As was pointed out by SterlingArcher, there's a better option in ES6 in the form of Array.from.
var listOfNodes = Array.from($list);
You can use a simple for-loop
To go through these arrays just don't use forEach, with that you will go through every property but you want the numbers only
Jquery uses a combination of arrays and associative array (objects in Javascript)
So it has auto incremented keys and words as keys
whenever I try to print an Array I get a lot of , and Chrome (my preferred browser) chokes the CPU.
How does it come, that it cannot print a simple Array to a string?
.toString() prints all values in the array from the first to the last values in order, separating each one by a comma.
new Array(276959) defines an array with 276959 empty entries, so the array itself has no values; it just has 276959 placeholders. When you use .toString(), there are no values to output, but the commas will still appear since the array has 276959 placeholders.
When you make
new Array(276959)
you are actually creating an array of 276959 values.
Since it doesn't have any content, each value is empty, so you only see the commas (separators) when you try to print it.
I have an Array of Objects which has a key say PhoneNumber (along with other key-value pairs). I have a phone number value that I'm looking for in this Array. I'm performing a linear search on this array for the phone number and breaking the loop as soon as I find the object (hence If I'm lucky, I may not need traverse through entire Array).
Best case here is only if I find the phone number in Array (and don't search further), but chances are more that I'll not find it, and will traverse whole array in vain.
Update
I thought to provide this, the search space (the Array of Objects) will have around ~500 elements, so looking specifically at this linear search may not be a performance concern, but there are many other tasks which are performed alongside this search, so I'm looking for as many micro-optimizations as possible.
Update 2 (In response to Elias Van Ootegem's comment)
I think my Array has something inappropriate in its structure such that neither of JSON.stringify() (Uncaught TypeError: Converting circular structure to JSON) or Ext.JSON.encode() (Maximum call stack exceeded) works to convert array into JSON string.
But, anyway to do this even faster?
Create a lookup object, which maps the phone number (as key) to the index inside the array.
var dataset = [{phone:'0123 456 689'},{phone:'0987 654 321'},...];
var lookup = {'0123 456 689':0,'0987 654 321':1,...};
// search like this...
var number = '0987 654 321';
var obj = dataset[lookup[number]];
But this is probably overkill for most use-cases, as a linear search should be fast enough for users even with thousands of entries.
It deppends on the usage.
If you use this array many times, you should use a map instead of using an array. Create a hash with {key: data}, and get the data given its key. (convert the array to a hash in the javascript)
If you only use the array once, the process of converting it to a map will take longer than the search itself. The best way, linear search.
The cost of boths solutions are (considering n: array lenght, and m, number of searches):
first solution:
n*log(n) + m * log(n)
Secons solution:
n*m