Combine Arrays in Order JavaScript - javascript

I have a few arrrays which I am trying to combine in a certain order. For example, lets say I have three arrays:
var arrayOne = [1a, 1b, 1c];
var arrayTwo = [2a, 2b, 2c];
var arrayThree [3a, 3b, 3c];
how would I get something like this?
var combinedArray = [1a, 2a, 3a, 1b, 2b, 3b, 1c, 2c, 3c]
EDIT
Ok, I am going to add a little more to my story here since I have gotten some great responses and answers from everyone. Maybe this will be clearer. I have a SharePoint list which I am getting all of my information from. I am using SPServices to get my data from the list. I am also getting the version history of each list item and placing them into arrays so I can pull the data out of the SPServices loop and use it outside of the SharePoint stuff so I can try to order and display it as I want. (Please do not move this to SharePoint ).
This is all going to have to happen at runtime. So here is the first part. I am declaring global variables for each one of my list items:
var proModified6 = new Array();
var proHistory = new Array();
var assignedTo = new Array();
var startDate = new Array();
var endDate = new Array();
var status = new Array();
var project = new Array();
var history = new Array();
var listItems = new Array();
var regex = new RegExp("");
var i = 0;
Then I am filling the arrays with the SharePoint list info ( I am not going to put them all but each has a call like this one)
$().SPServices({
operation: "GetVersionCollection",
async: false,
webURL: "http://devchrisl01/test",
strlistID: "NewProjects",
strlistItemID: proID[i],
strFieldName: "Title",
completefunc: function (xdata, Status) {
$(xdata.responseText).find("Version").each(function() {
//alert(xdata.responseXML.xml);
var xitem = $(this);
var ID = xitem.attr('ID');
var Project = xitem.attr('Title');
var Modified = xitem.attr('Modified').split('T')[0];
var ModifiedTime = xitem.attr('Modified').substring(11, 19);
//var modifiedUl = "<td><b>" + Modified + " " + ModifiedTime + "</b></td>";
//$('#versionList'+i+'').append(modifiedUl);
project.push(Project);
proModified2.push(Modified + ModifiedTime)
// just looking at my data here not really part of my problem
var data = "<tr><td><b>" + Modified + " " + ModifiedTime + "</b></td><td>" + Project + "</td></tr>";
$('#versionList'+i+'').append(data);
});
}
});
After is where my question has come into play. I am getting all of my data back I need. I have not found a better way to store all of the list information and pull it out of the SPServices besides using an array for each. The kicker is I am not going to know how many arrays there are going to be or how long. Eventually this is going to be dynamic. (PAIN IN THE ASS ) so here are the arrays:
var modifiedDate = [proModified1, proModified2, proModified3, proModified4, proModified5, proModified6];
var projectHistory = [history];
var projectTitle = [project];
var projectAssignedTo = [assignedTo];
var projectStartDate = [startDate];
var projectEndDate = [endDate];
var projectStatus = [status];
Each one is going to be different. There is not going to be the same amount of them either for each user. I have just made my list static to build on first. List dynamics will be another question later :0
Is there going to be a way for me to do with these arrays like I asked in my simple example? See why I went simple first lol.

Edit: Updated comparator as Salmon pointed out that it should return -1, 0 or 1.
Try below,
var arrayOne = ["1a", "1b", "1c"];
var arrayTwo = ["2a", "2b", "2c"];
var arrayThree = ["3a", "3b", "3c"];
var combinedArray = arrayOne
.concat(arrayTwo, arrayThree) //Concatenate the array.. can add any number of arrays
.sort(function(a, b) { //Custom comparator for your data
var a1 = a.charAt(1);
var b1 = b.charAt(1);
if (a1 == b1) return 0;
if (a1 < b1) return -1;
return 1;
});
Note: The custom comparator function is very specific to your data. Update the function as you need.
DEMO

From my understanding, you're looking for a zip function, like in python. There's no such built-in in javascript, but it's easy to write, for example:
zip = function() {
var
args = [].slice.call(arguments, 0),
len = Math.max.apply(Math, args.map(function(x) { return x.length })),
out = [];
for (var i = 0; i < len; i++)
out.push(args.map(function(x) { return x[i] }));
return out;
}
Applied to your arrays
var arrayOne = ["1a", "1b", "1c"];
var arrayTwo = ["2a", "2b", "2c"];
var arrayThree = ["3a", "3b", "3c"];
zipped = zip(arrayOne, arrayTwo, arrayThree);
this creates a nested array:
[["1a", "2a", "3a"], ["1b", "2b", "3b"], ["1c", "2c", "3c"]]
which you can use as is or convert to a flat one:
flat = [].concat.apply([], zipped)

If the length of the three arrays will always be the same of each other:
var arrayOne = ["1a", "1b", "1c"];
var arrayTwo = ["2a", "2b", "2c"];
var arrayThree = ["3a", "3b", "3c"];
var newArray = [];
for (var i = 0, len = arrayOne.length; i < len; i++) {
newArray.push(arrayOne[i], arrayTwo[i], arrayThree[i]);
}
console.log(newArray); //1a,2a,3a,1b,2b,3b,1c,2c,3c
But if your arrays won't always be the same length, we will need to use the greatest length of the three arrays and skip missing indexes, so it will be like this:
var arrayOne = ["1a", "1b", "1c", "1d"];
var arrayTwo = ["2a", "2b", "2c"];
var arrayThree = ["3a", "3b"];
var newArray = [];
var len = Math.max(arrayOne.length, arrayTwo.length, arrayThree.length);
for (var i = 0; i < len; i++) {
if (i in arrayOne) {
newArray.push(arrayOne[i]);
}
if (i in arrayTwo) {
newArray.push(arrayTwo[i]);
}
if (i in arrayThree) {
newArray.push(arrayThree[i]);
}
}
console.log(newArray); //1a,2a,3a,1b,2b,3b,1c,2c,1d
The reason to use i in arr (as difference of other checks), is because this will allow you to keep any falsish value 0,"",false,null,undefined,NaN intact. Otherwise it will be very hard to leave them alone (specially undefined values inside your array)
Performance tests between my answer and the currently most upvoted answer

I'd suggest using the default JS sort() method with a callback of some kind. If the elements if the array are all like /[0-9][a-z]/, this will give you the desired result:
//concat arrays first, of course
function specialSort(a,b)
{
if(a[1] < b[1])
{
return -1;
}
if(a[1] > b[1])
{
return 1;
}
return 0;
}
//using wsanville's expample: combinedArray = ["1a", "1b", "1c", "2a", "2b", "2c", "3a", "3b", "3c"]
combinedArray = combinedArray.sort(specialSort);
//result: combinedArray = ["1a", 2a", "3a", "1b", "2b", "3b", "1c", "2c", "3c"]
Hope this works for you...

You can simply do:
var arrayOne = ["1a", "1b", "1c"];
var arrayTwo = ["2a", "2b", "2c", "2d", "2e"];
var arrayThree = ["3a", "3b", "3c", "3d"];
var combinedArray = [];
for (var i = 0, j = Math.max(arrayOne.length, arrayTwo.length, arrayThree.length); i < j; i++) {
if (arrayOne.length) combinedArray.push(arrayOne.shift());
if (arrayTwo.length) combinedArray.push(arrayTwo.shift());
if (arrayThree.length) combinedArray.push(arrayThree.shift());
}
alert(combinedArray.join(", "));​
This should probably work for variable length arrays. Demo here.

Related

Generating an array with sub-arrays

I realize this is a somewhat off manner of operations, but for the sake of possibility, I'm wondering if anyone can help?
Here array2 is holding the end state I would like array1 to hold (only I want to do it with the for loop. It's fine that each sub_array's have to be initialized as their own variables, I'm just trying to get the array1 to hold N number of sub_arrays via the loop.
Here is the example I've tried, but trying to "compile" it via a string doesn't allow the sub_arrays to be called in a useable manner.
var numberOfSubArrays = 3
var sub_array1 = []
var sub_array2 = []
var sub_array3 = []
var array1 = []
var array2 = [sub_array1,sub_array2,sub_array3]
for (var i = 0; i < numberOfSubArrays; i++) {
array1[i] = "sub_array" + i
}
Any thoughts would be much appreciated!
var numberOfSubArrays = 3
var sub_array1 = [1]
var sub_array2 = [2]
var sub_array3 = [3]
var array1 = []
// we don't need array2 at all
//var array2 = [sub_array1,sub_array2,sub_array3]
// you need to count from 1..n, as you named your sub_arrays like that
for (var i = 1; i <= numberOfSubArrays; i++) {
// you can use eval, but be careful, eval is evil!
array1[i-1] = eval("sub_array" + i)
}
console.log(array1);
Using eval is yucky. This will work in browsers:
var numberOfSubArrays = 3
var sub_array1 = []
var sub_array2 = []
var sub_array3 = []
var array1 = []
var array2 = [sub_array1,sub_array2,sub_array3]
for (var i = 0; i < numberOfSubArrays; i++) {
array1[i] = window["sub_array" + i + 1];
}
In browsers, "global" vars are really objects in "window".
Note: this will not work in tools like jsfiddle, because they put your code inside a function (that you don't see).

array object manipulation to create new object

var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var expect = [
{month:"JAN",val: {"UK":"24","AUSTRIA":"64","ITALY":"21"}},
{month:"FEB",val: {"UK":"14","AUSTRIA":"24","ITALY":"22"}},
{month:"MAR",val: {"UK":"56","AUSTRIA":"24","ITALY":"51"}}
];
I have array of objects which i need to reshape for one other work. need some manipulation which will convert by one function. I have created plunker https://jsbin.com/himawakaju/edit?html,js,console,output
Main factors are Month, Country and its "AC" value.
Loop through, make an object and than loop through to make your array
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var outTemp = {};
actual.forEach(function(obj){ //loop through array
//see if we saw the month already, if not create it
if(!outTemp[obj.month]) outTemp[obj.month] = { month : obj.month, val: {} };
outTemp[obj.month].val[obj.country] = obj.AC; //add the country with value
});
var expected = []; //convert the object to the array format that was expected
for (var p in outTemp) {
expected.push(outTemp[p]);
}
console.log(expected);
Iterate through array and create new list
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var newList =[], val;
for(var i=0; i < actual.length; i+=3){
val = {};
val[actual[i].country] = actual[i]["AC"];
val[actual[i+1].country] = actual[i+1]["AC"];
val[actual[i+2].country] = actual[i+2]["AC"];
newList.push({month: actual[i].month, val:val})
}
document.body.innerHTML = JSON.stringify(newList);
This is the correct code... as above solution will help you if there are 3 rows and these will be in same sequnece.
Here is perfect solution :
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var tmpArray = [];
var obj =[];
for(var k=0; k<actual.length; k++){
var position = tmpArray.indexOf(actual[k].month);
if(position == -1){
tmpArray.push(actual[k].month);
val = {};
for(var i=0; i<actual.length; i++){
if(actual[i].month == actual[k].month){
val[actual[i].country] = actual[i]["AC"];
}
}
obj.push({month: actual[k].month, val:val});
}
}

How to extract values from an array of arrays in Javascript?

I have a variable as follows:
var dataset = {
"towns": [
["Aladağ", "Adana", [35.4,37.5], [0]],
["Ceyhan", "Adana", [35.8,37], [0]],
["Feke", "Adana", [35.9,37.8], [0]]
]
};
The variable has a lot of town data in it. How can I extract the first elements of the third ones from the data efficiently? I,e, what will ... be below?
var myArray = ...
//myArray == [35.4,35.8,35.9] for the given data
And what to do if I want to store both values in the array? That is
var myArray = ...
//myArray == [[35.4,37.5], [35.8,37], [35.9,37.8]] for the given data
I'm very new to Javascript. I hope there's a way without using for loops.
On newer browsers, you can use map, or forEach which would avoid using a for loop.
var myArray = dataset.towns.map(function(town){
return town[2];
});
// myArray == [[35.4,37.5], [35.8,37], [35.9,37.8]]
But for loops are more compatible.
var myArray = [];
for(var i = 0, len = dataset.towns.length; i < len; i++){
myArray.push(dataset.towns[i][2];
}
Impossible without loops:
var myArray = [];
for (var i = 0; i < dataset.towns.length; i++) {
myArray.push(dataset.towns[i][2][0]);
}
// at this stage myArray = [35.4, 35.8, 35.9]
And what to do if I want to store both values in the array?
Similar, you just add the entire array, not only the first element:
var myArray = [];
for (var i = 0; i < dataset.towns.length; i++) {
myArray.push(dataset.towns[i][2]);
}
// at this stage myArray = [[35.4,37.5], [35.8,37], [35.9,37.8]]

How do I take an array of strings and filter them?

I have an array of strings in jQuery. I have another array of keywords that I want to use to filter the string array.
My two arrays:
var arr = new Array("Sally works at Taco Bell", "Tom drives a red car", "Tom is from Ohio", "Alex is from Ohio");
var keywords = new Array("Tom", "Ohio");
How can I filter the arr array using the keywords array in jQuery? In this situation it would filter out "Sally works at Taco Bell" and keep the rest.
Below is the actual code I am using.
var keywords= [];
var interval = "";
var pointer = '';
var scroll = document.getElementById("tail_print");
$("#filter_button").click(
function(){
var id = $("#filter_box").val();
if(id == "--Text--" || id == ""){
alert("Please enter text before searching.");
}else{
keywords.push(id);
$("#keywords-row").append("<td><img src=\"images/delete.png\" class=\"delete_filter\" /> " + id + "</td>");
}
}
);
$(".delete_filter").click(
function(){
($(this)).remove();
}
);
function startTail(){
clearInterval(interval);
interval = setInterval(
function(){
$.getJSON("ajax.php?function=tail&pointer=" + pointer + "&nocache=" + new Date(),
function(data){
pointer = data.pointer;
$("#tail_print").append(data.log);
scroll.scrollTop = scroll.scrollHeight;
});
}, 1000);
}
The whole purpose of this is to allow the user to filter log results. So the user performs an action that starts startTail() and $.getJSON() retrieves a JSON object that is built by a PHP function and prints the results. Works flawlessly. Now I want to give the user the option to filter the incoming tailing items. The user clicks a filter button and jQuery takes the filter text and adds it to the keywords array then the data.log from the JSON object is filtered using the keywords array and then appended to the screen.
I also have a delete filter function that isn't working. Maybe someone can help me with that.
$.grep( arr, $.proxy(/./.test, new RegExp(keywords.join("|"))));
without jQuery:
arr.filter(/./.test.bind(new RegExp(keywords.join("|"))));
jQuery's word for "filter" is grep
var arr = ["Sally works at Taco Bell", "Tom drives a red car", "Tom is from Ohio", "Alex is from Ohio"];
var keywords = ["Tom", "Ohio"];
var regex = new RegExp(keywords.join("|"));
result = $.grep(arr, function(s) { return s.match(regex) })
var filtered = [];
var re = new RegExp(keywords.join('|'));
for (var i=0; i<arr.length; i++) {
if (re.search(arr[i])) {
filtered.append(arr[i]);
}
}
UPDATE
Since there's better answers here from a jQuery perspective, I modified my answer to a vanilla JavaScript approach, just for those who might need to do this without jQuery.
Top of head, and untested. As a jQuery plugin:
(function($) {
$.foo = function(needle, haystack) {
return $.grep(haystack, function () {
var words = this.split(' '),
flag = false
;
for(var i=0; i < words.length; i++) {
flag = $.inArray(words[i], needle);
if (flag) { break; }
}
return flag;
});
};
})(jQuery);
Then you can (supposedly) run that like:
var bar = $.foo(keywords, arr);
You could use the [filter][1] function, but either way you'll need to loop through both arrays. You can use indexOf to check if a string is contained within another string.
var arr = ["Sally works at Taco Bell", "Tom drives a red car", "Tom is from Ohio", "Alex is from Ohio"];
var keywords = ["Tom", "Ohio"];
var filtered = [];
for(var i = 0; i < arr.length; i++) {
for(var j = 0; j < keywords.length; j++) {
if (arr[i].indexOf(keywords[j]) > -1) {
filtered.push(arr[i]);
break;
}
}
}
console.log(filtered);
Live example
Using jQuery awesome powers:
var keywords = ["Tom", "Ohio"];
$(["Sally works at Taco Bell", "Tom drives a red car", "Tom is from Ohio", "Alex is from Ohio"]).filter(function(k, v) {
return v.match("(" + keywords.join("|") + ")");
});
var keywords = ['Tom', 'Ohio'];
var arr = ['Sally works at Taco Bell', 'Tom drives a red car', 'Tom is from Ohio', 'Alex is from Ohio'];
var matcher = new RegExp(keywords.join('|'));
var newarr = [];
$.each(arr, function(index, elem) {
if (elem.match(matcher)) {
newarr.push(elem);
}
});
console.log(newarr);
fiddle: http://jsfiddle.net/LQ92u/1/

How do I divide a complex string into 3 seperate arrays?

Here's where I am:
I started with an array...cleaned it up using 'regex'.
Now I have this...each item has three values
mystring = 4|black|cat, 7|red|dog, 12|blue|fish
Here's where I want to be:
I want to end up with three arrays.
array1=("4","7","12")
array2=("black","red","blue")
array3=("cat","dog","fish")
I also want to do this without leaving the page...preferably using javascript
I understand the theory, but I'm getting tangled in the syntax.
I'd use John Resig's famous "search and don't replace" method here, it's perfect for it:
var arr1 = [], arr2 = [], arr3 = [],
mystring = "4|black|cat, 7|red|dog, 12|blue|fish";
mystring.replace(/(\d+)\|([^\|]+)\|([^,]+)/g, function ($0, $1, $2, $3) {
arr1.push($1);
arr2.push($2);
arr3.push($3);
});
Example
You want to use the split() method :
var res = mystring.split(','); //will give you an array of three strings
var subres = res[0].split('|'); //will give you an array with [4, black, cat]
//etc...
Like this?:
var values = mystring.split(',');
var arrays = new Array();
for(var i=0; i < values.length; i++) {
var parts = values[i].split('|');
for(var j = 0; j < parts.length;j++) {
if(!arrays[j]) {
arrays[j] = new Array();
}
arrays[j].push(parts[j]);
}
}
Will give you an array that contains those three arrays.
var str = '4|black|cat, 7|red|dog, 12|blue|fish';
var tmp = str.split(',');
var firstArray = Array();
var secondArray = Array();
var thirdArray = Array();
for( var i in tmp ){
var splitted = tmp[i].split('|');
//alert(true);
firstArray[i]=splitted[0];
secondArray[i]=splitted[1];
thirdArray[i]=splitted[2];
}

Categories

Resources