Sorting 2D javascript array - javascript

I have an array containing a list of tags and count.
tags_array[0] = tags;
tags_array[1] = tags_count;
I need to sort the arrays base on the count so that I can pick out the top few tags.

Sort one, while storing the sort comparisons. Then sort the other using those results:
var res = [];
tags_count.sort( function( a, b ){ return res.push( a=a-b ), a; } );
tags.sort( function(){ return res.shift(); } );

Supposing tags and tags_count are 2 arrays of same length, I would first build a proper array of objects :
var array = [];
for (var i=0; i<tags_count.length; i++) {
array.push({tag:tags[i], count:tags_count[i]});
}
And then sort on the count :
array.sort(function(a, b) {return a.count-b.count});
If you need to get your arrays back after that, you may do
for (var i=0; i<array.length; i++) {
tags[i] = array[i].tag;
tags_count[i] = array[i].count;
}
Demonstration

Assuming that both tags and tags_count are arrays with the same length (that part of the question wasn't too clear), the following is one way to do the trick.
var tags_array = new Array();
for (var i = 0; i < tags.length; i++)
{
tags_array[i] = {};
tags_array[i].tagName = tags[i];
tags_array[i].tagCount = tags_count[i];
}
tags_array.sort(function(a,b){return b.tagCount-a.tagCount});
One should note that it might be possible to structure the data in this way from the start instead of rewriting it like this, in which case that is preferable. Likewise, a better structure can be used to save the data, but this will work.

Related

Extract a value from a Custom Javascript array when it's a component of a string value within an array

I'm looking to extract the values 'adult' and '2ndclass' from this custom javascript array in separate javascript variables for each value. Anyone has any ideas on how to do this?
In the following case, there are 2 products added to cart but I would like to have the flexibility to always grab any existing values for each product that is added to cart regardless of the amount added. Is that possible?
[
'pass/DE-NO-RS-BE-FI-PT-BG-DK-LT-LU-HR-LV-FR-HU-SE-SI-ME-SK-GB-IE-MK-EE-CH-GR-IT-ES-AT-CZ-PL-RO-NL-TR-BA/**adult/2ndclass**',
'pass/DE-NO-RS-BE-FI-PT-BG-DK-LT-LU-HR-LV-FR-HU-SE-SI-ME-SK-GB-IE-MK-EE-CH-GR-IT-ES-AT-CZ-PL-RO-NL-TR-BA/**youth/2ndclass**'
]
Thank you in advance for your help
You can also use RegExp to get those values out.
var arr = [
"pass/DE-NO-RS-BE-FI-PT-BG-DK-LT-LU-HR-LV-FR-HU-SE-SI-ME-SK-GB-IE-MK-EE-CH-GR-IT-ES-AT-CZ-PL-RO-NL-TR-BA/**adult/2ndclass**",
"pass/DE-NO-RS-BE-FI-PT-BG-DK-LT-LU-HR-LV-FR-HU-SE-SI-ME-SK-GB-IE-MK-EE-CH-GR-IT-ES-AT-CZ-PL-RO-NL-TR-BA/**youth/2ndclass**"
];
var results = [];
for (var i=0; i < arr.length; i++) {
var matches = arr[i].match(/\*\*(.+)\/(.+)\*\*/);
if(matches && matches.length >= 3)
results.push([matches[1], matches[2]]);
}
console.log(results);
You can try the code here https://jsfiddle.net/p84eftL7/1/
First of all i didn't get your question completely. But as far as i can understand you want those 2 values at the end of the strings from an array. You can try something like this
var a, b;
for(s in YOUR_ARRAY){
[...other, a, b] = YOUR_ARRAY[s].split("/");
console.log(a, b);
//Do whatever you want to do with a,b
}
Let me explain myself, Firstly you would require to iterate over your array thats why we have a 'for' loop here. Then for each string which is given by 'YOUR_ARRAY[s]' you are splitting the string with '/' as a delimiter. Rest of the thing is pretty simple.
For your reference go through these links
https://www.w3schools.com/js/js_loop_for.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
UPDATE:
As mentioned in the comments. If you want to have a function for this then
function processValues(arr){
var a, b;
for(s in arr){
[...other, a, b] = arr[s].split("/");
console.log(a, b);
//Do whatever you want to do with a,b
}
}
processValues(YOUR_ARRAY);
In the end what I did was the following
As I had to reference back to the name of the variable I used the following to slice up the array so I could reference that using index numbers for the values I needed to retrieve:
function() {
var myStringArray = {{MY_ARRAY}};
var arrayLength = myStringArray.length;
var output = []
for (var i = 0; i < arrayLength; i++) {
var string = myStringArray[i].split("/",4)
/*pull index 2 and 3 from string and convert to string*/
output.push(string)
}
return output
}
After that I had to loop the new array that was being pushed out of the info as mentioned above
Since I only needed to split up particular indices from that NEW_ARRAY_2, I used the following to do that
function() {
var products = {{NEW_ARRAY_2}};
var arr = []
for (var i=0; i < products.length; i++) {
var prod = products[i];
var matches = prod[2];
arr.push(matches);
}
var list = arr.join(', ')
return list
}
SAMPLE RETURN for 2 products: 'adult, youth'
Thank you for your support

How to simplify this delete from array jQuery

I have an object and an array of categories that should be kept in the object. This snip https://jsfiddle.net/h10rkb6s/2/ ( see log ) works but I cant seems to shake the idea that it is to complicated for a simple search and keep task.
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"],"Others":["othericon1","othericon2"]};
var $categories = '["Spinners","Awesome"]';
var $CatsArray = JSON.parse($categories);
var groups = [];
for(var k in thz_icon_source) groups.push(k);
$.each($CatsArray,function(i,keep){
var index = groups.indexOf(keep);
if (index !== -1) {
groups.splice(index, 1);
}
});
for (var i = 0; i < groups.length; i++) {
delete thz_icon_source[groups[i]];
}
I tried with
$.each(thz_icon_source,function(category,icons){
$.each($CatsArray,function(i,keep){
var index = category.indexOf(keep);
if (index !== -1) {
delete thz_icon_source[category];
}
});
});
but this works only if 1 item is inside my search array.
Any help is appreciated.
There's no need to iterate over $CatsArray to find out which ones should be deleted. You will need to iterate over the keys of the object, and find out for each of them whether it should be deleted, to filter by that.
Leaving the top 3 lines of your script intact, you could simplify to
var keysToDelete = Object.keys(thz_icon_source).filter(function(groupName) {
return $CatsArray.indexOf(groupName) == -1;
});
($.grep would be the jQuery-ism for the filter method, if you are into that).
But assuming we don't even need those groups in an array, you could simply do
for (var groupName in thz_icon_source)
if ($CatsArray.indexOf(groupName) == -1)
delete thz_icon_source[groupName];
However, instead of deleting items from that object, I'd recommend to create a new object with only those that you want to keep. It's much easier to use:
var kept = {};
for (var i=0; i<$CatsArray.length; i++)
kept[$CatsArray[i]] = thz_icon_source[$CatsArray[i]];

How to "clean" an array in javascript?

I am stuck here. How can I clean this array:
{"data":[{"id":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]}
So that it looks like:
["5201521d42","52049e2591","52951699w4"]
I am using Javascript.
You just need to iterate over the existing data array and pull out each id value and put it into a new "clean" array like this:
var raw = {"data":[{"":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
var clean = [];
for (var i = 0, len = raw.data.length; i < len; i++) {
clean.push(raw.data[i].id);
}
Overwriting the same object
var o = {"data":[{"id":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
for (var i = o.data.length; i--; ){
o.data[i] = o.data[i].id;
}
What you're doing is replacing the existing object with the value of its id property.
If you can use ES5 and performance is not critical, i would recommend this:
Edit:
Looking at this jsperf testcase, map vs manual for is about 7-10 times slower, which actually isn't that much considering that this is already in the area of millions of operations per second. So under the paradigma of avoiding prematurely optimizations, this is a lot cleaner and the way forward.
var dump = {"data":[{"id":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
var ids = dump.data.map(function (v) { return v.id; });
Otherwise:
var data = dump.data;
var ids = [];
for (var i = 0; i < data.length; i++) {
ids.push(data[i].id);
}
Do something like:
var cleanedArray = [];
for(var i=0; i<data.length; i++) {
cleanedArray.push(data[i].id);
}
data = cleanedArray;
Take a look at this fiddle. I think this is what you're looking for
oldObj={"data":[{"":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
oldObj = oldObj.data;
myArray = [];
for (var key in oldObj) {
var obj = oldObj[key];
for (var prop in obj) {
myArray.push(obj[prop]);
}
}
console.log(myArray)
Use Array.prototype.map there is fallback code defined in this documentation page that will define the function if your user's browser is missing it.
var data = {"data":[{"":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
var clean_array = [];
for( var i in data.data )
{
for( var j in data.data[i] )
{
clean_array.push( data.data[i][j] )
}
}
console.log( clean_array );
You are actually reducing dimension. or you may say you are extracting a single dimension from the qube. you may even say selecting a column from an array of objects. But the term clean doesn't match with your problem.
var list = [];
var raw = {"data":[{"id":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]};
for(var i=0; i < raw.data.length ; ++i){
list.push(raw.data[i].id);
}
Use the map function on your Array:
data.map(function(item) { return item.id; });
This will return:
["5201521d42", "52049e2591", "52951699w4"]
What is map? It's a method that creates a new array using the results of the provided function. Read all about it: map - MDN Docs
The simplest way to clean any ARRAY in javascript
its using a loop for over the data or manually, like this:
let data = {"data":[{"id":"5201521d42"},{"id":"52049e2591"},
{"id":"52951699w4"}]};
let n = [data.data[0].id,data.data[1].id, data.data[2].id];
console.log(n)
output:
(3) ["5201521d42", "52049e2591", "52951699w4"]
Easy and a clean way to do this.
oldArr = {"data":[{"id":"5201521d42"},{"id":"52049e2591"},{"id":"52951699w4"}]}
oldArr = oldArr["data"].map(element => element.id)
Output: ['5201521d42', '52049e2591', '52951699w4']

fastest way to loop through an array

I want to return an array when one of the elements matches an item within an array.
Is the below code the fastest way to loop through an array when a value matches in a javascript array of arrays?
Note : Welcome any suggestions to modify the variable relatedVideosArray to make it a different data structure for better performance.
var relatedVideosArray = [
["1047694110001"],
["1047694111001", "1019385098001","1020367665001","1020367662001", "1019385097001", "1020367667001"],
["1040885813001"],
["1019385094001", "1019385096001"],
["952541791001", "952544511001", "952544512001", "952544508001", "952541790001","952580933001", "952580934001", "1051906367001"]
]
function getRelatedVideos(videoClicked){
var tempStoreArray = [];
var getCurrentId = videoClicked;
var relVideoslen = relatedVideosArray.length;
for(var i in relatedVideosArray) {
tempStoreArray = relatedVideosArray[i];
for(var j in tempStoreArray){
if(tempStoreArray[j] == getCurrentId){
return relatedVideosArray[i];
}
}
}
}
Update: I initially thought of making a key of video ids and values as all the related ids, but I want to display the key as well as all the related ids if any of the ids within the value array are clicked. Hope this helps to explain the constraint I have.
Modern day browsers support Array indexOf.
For the people saying the array indexOf is slower, basic tests on speed.
var values = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
console.time("for");
for(var i=0;i<1000;i++){
for(var j=0;j<=values.length;j++){
if(values[j]===20) break;
}
}
console.timeEnd("for");
console.time("reverse for");
for(i=0;i<1000;i++){
for(var j=values.length-1;j>=0;j--){
if(values[j]===1) break;
}
}
console.timeEnd("reverse for");
console.time("while");
for(i=0;i<1000;i++){
var j=0;
while (j<values.length){
if(values[j]===20) break;
j++;
}
}
console.timeEnd("while");
console.time("reverse while");
for(i=0;i<1000;i++){
var j=values.length-1;
while (j>=0){
if(values[j]===1) break;
j--;
}
}
console.timeEnd("reverse while");
console.time("indexOf");
for(var i=0;i<1000;i++){
var x = values.indexOf(20);
}
console.timeEnd("indexOf");
console.time("toString reg exp");
for(var i=0;i<1000;i++){
var x = (/(,|^)20(,|$)/).test(values.toString);
}
console.timeEnd("toString reg exp");
Two possible solutions:
var relatedVideosArray = [
["1047694110001"],
["1047694111001", "1019385098001","1020367665001","1020367662001", "1019385097001", "1020367667001"],
["1040885813001"],
["1019385094001", "1019385096001"],
["952541791001", "952544511001", "952544512001", "952544508001", "952541790001","952580933001", "952580934001", "1051906367001"]
]
//var getCurrentId = "1019385098001";
var getCurrentId = "1040885813001";
console.time("indexOf");
var tempStoreArray = [];
for(var i = relatedVideosArray.length-1; i>=0; i--){
var subArr = relatedVideosArray[i];
if(subArr.indexOf(getCurrentId)!==-1){
tempStoreArray.push(subArr);
}
}
console.timeEnd("indexOf");
console.log(tempStoreArray);
console.time("toString reg exp");
var tempStoreArray = [];
var re = new RegExp("(,|^)" + getCurrentId + "(,|$)");
for(var i = relatedVideosArray.length-1; i>=0; i--){
var subArr = relatedVideosArray[i];
if(re.test(subArr.toString())){
tempStoreArray.push(subArr);
}
}
console.timeEnd("toString reg exp");
console.log(tempStoreArray);
I believe so if you keep your current structure. Unless you have a way of 'flattening' the array first, so that rather than being nested, there is simply one array with all the values. If this is out of your control or impractical, then you have no other choice than to iterate over every element and its elements.
Otherwise, would you be able to add the values to a map? The current video id would be the key, and the value would be the list of related videos.
If you have control over the data structure then I highly recommend changing it to something more amenable to the type of searches you are performing. First thing that comes to mind is an array of associative arrays. Each of your video arrays would be keyed with the video id ( set the value to anything you want ). That would make your search O(n), where n = the total number of video lists you have.
I'll post some code for this when I get in front of the computer.

A good way to associate a counter to each member of an array in Javascript?

I have an array of strings in Javascript like `var elements = ["string1", "string2"]; The array is created dynamically so it could contain any number of strings. I want to associate a counter to each element of the array. The counter will increment or decrement during the webpage's life.
I was going to try element["string1"].counter = 1; but it didn't work.
What's a good way to implement this?
If you had an array var elements = ["string1", "string2"], you could not access an element with elements["string1"], you are using the value not the index. elements[0] is the correct form of access to the element, using the numerical key.
Even then, strings are special types of object and do not appear to take additional parameters readily, at least not when I tested a moment ago. Which is odd.
You could quickly knock the array in to a set of objects with separate text and counter components.
var elements = ["string1", "string2"];
var elementsWithCounter = [];
for(var index = 0; index < elements.length; index++) {
elementsWithCounter[i] = { text: elements[index], counter: 1 };
}
You could also create a "hash table" using a plain object such as:
var counter = {};
for(var i = elements.length; i--; ) {
counter[elements[i]] = 1;
}
Then you could increment the counter with:
counter['string1'] += 1;
or
counter[elements[0]] += 1;
This might help you.
elementArray = ["string1", "string2"]
function setCounter(str, val) {
for (var i = 0; i < elementArray.length; i++) {
if (str === elementArray[i]) elementArray[i].counter = val;
}
}
function getCounter(str) {
for (var i = 0; i < elementArray.length; i++) {
if (str === elementArray[i]) return elementArray[i].counter;
}
}
setCounter("string1", 5);
getCounter("string1");
Alternatively just access elementArray[index].counter
Javascript primitives/built in objects can't have properties/attributes added to their prototype (i.e. String.prototype.counter = -1 doesn't work correctly). Image, String, Date, Array all can't have properties added.
Maybe instead of a string you should make it an object, similar to what Orbling has posted.

Categories