breaking from a for look inside a reucrsive function - javascript

Please see the fiddle.
I am bit stuck with why the loop does not break the way I intended.
input is an object, indexed with some kind of id. And the values are the children ids. so, I am trying to filter out (here it is hard coded as d) a node and its children. For example, for d, there is only one child, h. so, I was expecting an output ['d', 'h']. This is because, once the filter condition met (c === 'd'), it discards all previous value, and just recurse to its children (only h) in this case. Once the recursion to children finished, the break should terminate the for loop. but as I see from the output, the for loop doesn't breaks and continues with (c -> g). How to make this so once the filter met, it only output the node and all its children ['d', 'h'] in this case.
const input = {
a: ['b', 'c'],
b: ['d', 'e', 'f'],
c: ['g'],
d: ['h'],
}
let data = [];
const recur = (d) => {
const ch = input[d]
if (!ch) {
return;
}
for (let i = 0; i < ch.length; i++) {
console.log(data)
const c = ch[i]
data.push(c)
if (c === 'd') {
data = [c];
console.log("reset data", data)
recur(c)
break
}
recur(c)
}
}
recur('a')
console.log("end: ", data)
output: end: ["d", "h", "c", "g"]

This is what I came up with. https://jsfiddle.net/j6s1vouv/4/ There need a way to inform the parent that, the filter is met and should skip the sibling iteration.
const input = {
a: ['b', 'c'],
b: ['d', 'e', 'f'],
c: ['g'],
d: ['h'],
}
const recur = (d) => {
const ch = input[d]
if (!ch) {
return {
data: []
};
}
let out = [];
for (let i = 0; i < ch.length; i++) {
const c = ch[i]
const x = recur(c)
if (x.skip) { // if any of the child met filter
return x
}
if (c === 'd') { // current id met filter
return {
data: [c].concat(x.data),
skip: true
}
}
out = out.concat([c], x.data)
}
return {
data: out
}
}
console.log("end: ", recur('a').data)

Related

Sort does not work correctly when using a number [duplicate]

Is it possible to sort and rearrange an array that looks like this:
itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
to match the arrangement of this array:
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Unfortunately, I don’t have any IDs to keep track on. I would need to priority the items-array to match the sortingArr as close as possible.
Update:
Here is the output I’m looking for:
itemsArray = [
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]
Any idea how this can be done?
One-Line answer.
itemsArray.sort(function(a, b){
return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});
Or even shorter:
itemsArray.sort((a, b) => sortingArr.indexOf(a) - sortingArr.indexOf(b));
Something like:
items = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []
sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && item[1] == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
result.forEach(function(item) {
document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})
Here's a shorter code, but it destroys the sorting array:
result = items.map(function(item) {
var n = sorting.indexOf(item[1]);
sorting[n] = '';
return [n, item]
}).sort().map(function(j) { return j[1] })
If you use the native array sort function, you can pass in a custom comparator to be used when sorting the array. The comparator should return a negative number if the first value is less than the second, zero if they're equal, and a positive number if the first value is greater.
So if I understand the example you're giving correctly, you could do something like:
function sortFunc(a, b) {
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}
itemsArray.sort(sortFunc);
Case 1: Original Question (No Libraries)
Plenty of other answers that work. :)
Case 2: Original Question (Lodash.js or Underscore.js)
var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });
Case 3: Sort Array1 as if it were Array2
I'm guessing that most people came here looking for an equivalent to PHP's array_multisort (I did) so I thought I'd post that answer as well. There are a couple options:
1. There's an existing JS implementation of array_multisort(). Thanks to #Adnan for pointing it out in the comments. It is pretty large, though.
2. Write your own. (JSFiddle demo)
function refSort (targetData, refData) {
// Create an array of indices [0, 1, 2, ...N].
var indices = Object.keys(refData);
// Sort array of indices according to the reference data.
indices.sort(function(indexA, indexB) {
if (refData[indexA] < refData[indexB]) {
return -1;
} else if (refData[indexA] > refData[indexB]) {
return 1;
}
return 0;
});
// Map array of indices to corresponding values of the target array.
return indices.map(function(index) {
return targetData[index];
});
}
3. Lodash.js or Underscore.js (both popular, smaller libraries that focus on performance) offer helper functions that allow you to do this:
var result = _.chain(sortArray)
.pairs()
.sortBy(1)
.map(function (i) { return itemArray[i[0]]; })
.value();
...Which will (1) group the sortArray into [index, value] pairs, (2) sort them by the value (you can also provide a callback here), (3) replace each of the pairs with the item from the itemArray at the index the pair originated from.
this is probably too late but, you could also use some modified version of the code below in ES6 style. This code is for arrays like:
var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];
The actual operation :
arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));
The actual operation in ES5 :
arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
return arrayToBeSorted.includes(v);
});
Should result in arrayToBeSorted = [3,5]
Does not destroy the reference array.
function sortFunc(a, b) {
var sortingArr = ["A", "B", "C"];
return sortingArr.indexOf(a.type) - sortingArr.indexOf(b.type);
}
const itemsArray = [
{
type: "A",
},
{
type: "C",
},
{
type: "B",
},
];
console.log(itemsArray);
itemsArray.sort(sortFunc);
console.log(itemsArray);
Why not something like
//array1: array of elements to be sorted
//array2: array with the indexes
array1 = array2.map((object, i) => array1[object]);
The map function may not be available on all versions of Javascript
ES6
const arrayMap = itemsArray.reduce(
(accumulator, currentValue) => ({
...accumulator,
[currentValue[1]]: currentValue,
}),
{}
);
const result = sortingArr.map(key => arrayMap[key]);
More examples with different input arrays
I would use an intermediary object (itemsMap), thus avoiding quadratic complexity:
function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
var itemsMap = {};
for (var i = 0, item; (item = itemsArray[i]); ++i) {
(itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
}
return itemsMap;
}
function sortByKeys(itemsArray, sortingArr) {
var itemsMap = createItemsMap(itemsArray), result = [];
for (var i = 0; i < sortingArr.length; ++i) {
var key = sortingArr[i];
result.push([itemsMap[key].shift(), key]);
}
return result;
}
See http://jsfiddle.net/eUskE/
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
var found = false;
for(var j=0; j < itemsArray.length && !found; j++) {
if(itemsArray[j][1] == sortingArr[i]) {
sortedArray.push(itemsArray[j]);
itemsArray.splice(j,1);
found = true;
}
}
}
http://jsfiddle.net/s7b2P/
Resulting order: Bob,Jason,Henry,Thomas,Anne,Andrew
In case you get here needing to do this with an array of objects, here is an adaptation of #Durgpal Singh's awesome answer:
const itemsArray = [
{ name: 'Anne', id: 'a' },
{ name: 'Bob', id: 'b' },
{ name: 'Henry', id: 'b' },
{ name: 'Andrew', id: 'd' },
{ name: 'Jason', id: 'c' },
{ name: 'Thomas', id: 'b' }
]
const sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Object.keys(itemsArray).sort((a, b) => {
return sortingArr.indexOf(itemsArray[a].id) - sortingArr.indexOf(itemsArray[b].id);
})
let a = ['A', 'B', 'C' ]
let b = [3, 2, 1]
let c = [1.0, 5.0, 2.0]
// these array can be sorted by sorting order of b
const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))
const sortBy = (a, b, c) => {
const zippedArray = zip([a, b, c])
const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])
return zip(sortedZipped)
}
sortBy(a, b, c)
For getting a new ordered array, you could take a Map and collect all items with the wanted key in an array and map the wanted ordered keys by taking sifted element of the wanted group.
var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
result = sortingArr.map(k => (map.get(k) || []).shift());
console.log(result);
I hope that I am helping someone, but if you are trying to sort an array of objects by another array on the first array's key, for example, you want to sort this array of objects:
const foo = [
{name: 'currency-question', key: 'value'},
{name: 'phone-question', key: 'value'},
{name: 'date-question', key: 'value'},
{name: 'text-question', key: 'value'}
];
by this array:
const bar = ['text-question', 'phone-question', 'currency-question', 'date-question'];
you can do so by:
foo.sort((a, b) => bar.indexOf(a.name) - bar.indexOf(b.name));
This is what I was looking for and I did for sorting an Array of Arrays based on another Array:
It's On^3 and might not be the best practice(ES6)
function sortArray(arr, arr1){
return arr.map(item => {
let a = [];
for(let i=0; i< arr1.length; i++){
for (const el of item) {
if(el == arr1[i]){
a.push(el);
}
}
}
return a;
});
}
const arr1 = ['fname', 'city', 'name'];
const arr = [['fname', 'city', 'name'],
['fname', 'city', 'name', 'name', 'city','fname']];
console.log(sortArray(arr,arr1));
It might help someone
I had to do this for a JSON payload I receive from an API, but it wasn't in the order I wanted it.
Array to be the reference array, the one you want the second array sorted by:
var columns = [
{last_name: "last_name"},
{first_name: "first_name"},
{book_description: "book_description"},
{book_id: "book_id"},
{book_number: "book_number"},
{due_date: "due_date"},
{loaned_out: "loaned_out"}
];
I did these as objects because these will have other properties eventually.
Created array:
var referenceArray= [];
for (var key in columns) {
for (var j in columns[key]){
referenceArray.push(j);
}
}
Used this with result set from database. I don't know how efficient it is but with the few number of columns I used, it worked fine.
result.forEach((element, index, array) => {
var tr = document.createElement('tr');
for (var i = 0; i < referenceArray.length - 1; i++) {
var td = document.createElement('td');
td.innerHTML = element[referenceArray[i]];
tr.appendChild(td);
}
tableBody.appendChild(tr);
});
let sortedOrder = [ 'b', 'c', 'b', 'b' ]
let itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
a.itemsArray(function (a, b) {
let A = a[1]
let B = b[1]
if(A != undefined)
A = A.toLowerCase()
if(B != undefined)
B = B.toLowerCase()
let indA = sortedOrder.indexOf(A)
let indB = sortedOrder.indexOf(B)
if (indA == -1 )
indA = sortedOrder.length-1
if( indB == -1)
indB = sortedOrder.length-1
if (indA < indB ) {
return -1;
} else if (indA > indB) {
return 1;
}
return 0;
})
This solution will append the objects at the end if the sorting key is not present in reference array
const result = sortingArr.map((i) => {
const pos = itemsArray.findIndex(j => j[1] === i);
const item = itemsArray[pos];
itemsArray.splice(pos, 1);
return item;
});
this should works:
var i,search, itemsArraySorted = [];
while(sortingArr.length) {
search = sortingArr.shift();
for(i = 0; i<itemsArray.length; i++) {
if(itemsArray[i][1] == search) {
itemsArraySorted.push(itemsArray[i]);
break;
}
}
}
itemsArray = itemsArraySorted;
You could try this method.
const sortListByRanking = (rankingList, listToSort) => {
let result = []
for (let id of rankingList) {
for (let item of listToSort) {
if (item && item[1] === id) {
result.push(item)
}
}
}
return result
}
with numerical sortingArr:
itemsArray.sort(function(a, b){
return sortingArr[itemsArray.indexOf(a)] - sortingArr[itemsArray.indexOf(b)];
});
This seems to work for me:
var outputArray=['10','6','8','10','4','6','2','10','4','0','2','10','0'];
var template=['0','2','4','6','8','10'];
var temp=[];
for(i=0;i<template.length;i++) {
for(x=0;x<outputArray.length;x++){
if(template[i] == outputArray[x]) temp.push(outputArray[x])
};
}
outputArray = temp;
alert(outputArray)
Use the $.inArray() method from jQuery. You then could do something like this
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();
for(var i=sortingArr.length; i--;) {
var foundIn = $.inArray(sortingArr[i], itemsArray);
newSortedArray.push(itemsArray[foundIn]);
}
Use intersection of two arrays.
Ex:
var sortArray = ['a', 'b', 'c', 'd', 'e'];
var arrayToBeSort = ['z', 's', 'b', 'e', 'a'];
_.intersection(sortArray, arrayToBeSort)
=> ['a', 'b', 'e']
if 'z and 's' are out of range of first array, append it at the end of result
this.arrToBeSorted = this.arrToBeSorted.sort(function(a, b){
return uppthis.sorrtingByArray.findIndex(x => x.Id == a.ByPramaeterSorted) - uppthis.sorrtingByArray.findIndex(x => x.Id == b.ByPramaeterSorted);
});
You can do something like this:
function getSorted(itemsArray , sortingArr ) {
var result = [];
for(var i=0; i<arr.length; i++) {
result[i] = arr[sortArr[i]];
}
return result;
}
You can test it out here.
Note: this assumes the arrays you pass in are equivalent in size, you'd need to add some additional checks if this may not be the case.
refer link
refer

Javascript - Sorting an array of objects based on another array [duplicate]

Is it possible to sort and rearrange an array that looks like this:
itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
to match the arrangement of this array:
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Unfortunately, I don’t have any IDs to keep track on. I would need to priority the items-array to match the sortingArr as close as possible.
Update:
Here is the output I’m looking for:
itemsArray = [
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]
Any idea how this can be done?
One-Line answer.
itemsArray.sort(function(a, b){
return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});
Or even shorter:
itemsArray.sort((a, b) => sortingArr.indexOf(a) - sortingArr.indexOf(b));
Something like:
items = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []
sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && item[1] == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
result.forEach(function(item) {
document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})
Here's a shorter code, but it destroys the sorting array:
result = items.map(function(item) {
var n = sorting.indexOf(item[1]);
sorting[n] = '';
return [n, item]
}).sort().map(function(j) { return j[1] })
If you use the native array sort function, you can pass in a custom comparator to be used when sorting the array. The comparator should return a negative number if the first value is less than the second, zero if they're equal, and a positive number if the first value is greater.
So if I understand the example you're giving correctly, you could do something like:
function sortFunc(a, b) {
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}
itemsArray.sort(sortFunc);
Case 1: Original Question (No Libraries)
Plenty of other answers that work. :)
Case 2: Original Question (Lodash.js or Underscore.js)
var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });
Case 3: Sort Array1 as if it were Array2
I'm guessing that most people came here looking for an equivalent to PHP's array_multisort (I did) so I thought I'd post that answer as well. There are a couple options:
1. There's an existing JS implementation of array_multisort(). Thanks to #Adnan for pointing it out in the comments. It is pretty large, though.
2. Write your own. (JSFiddle demo)
function refSort (targetData, refData) {
// Create an array of indices [0, 1, 2, ...N].
var indices = Object.keys(refData);
// Sort array of indices according to the reference data.
indices.sort(function(indexA, indexB) {
if (refData[indexA] < refData[indexB]) {
return -1;
} else if (refData[indexA] > refData[indexB]) {
return 1;
}
return 0;
});
// Map array of indices to corresponding values of the target array.
return indices.map(function(index) {
return targetData[index];
});
}
3. Lodash.js or Underscore.js (both popular, smaller libraries that focus on performance) offer helper functions that allow you to do this:
var result = _.chain(sortArray)
.pairs()
.sortBy(1)
.map(function (i) { return itemArray[i[0]]; })
.value();
...Which will (1) group the sortArray into [index, value] pairs, (2) sort them by the value (you can also provide a callback here), (3) replace each of the pairs with the item from the itemArray at the index the pair originated from.
this is probably too late but, you could also use some modified version of the code below in ES6 style. This code is for arrays like:
var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];
The actual operation :
arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));
The actual operation in ES5 :
arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
return arrayToBeSorted.includes(v);
});
Should result in arrayToBeSorted = [3,5]
Does not destroy the reference array.
function sortFunc(a, b) {
var sortingArr = ["A", "B", "C"];
return sortingArr.indexOf(a.type) - sortingArr.indexOf(b.type);
}
const itemsArray = [
{
type: "A",
},
{
type: "C",
},
{
type: "B",
},
];
console.log(itemsArray);
itemsArray.sort(sortFunc);
console.log(itemsArray);
Why not something like
//array1: array of elements to be sorted
//array2: array with the indexes
array1 = array2.map((object, i) => array1[object]);
The map function may not be available on all versions of Javascript
ES6
const arrayMap = itemsArray.reduce(
(accumulator, currentValue) => ({
...accumulator,
[currentValue[1]]: currentValue,
}),
{}
);
const result = sortingArr.map(key => arrayMap[key]);
More examples with different input arrays
I would use an intermediary object (itemsMap), thus avoiding quadratic complexity:
function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
var itemsMap = {};
for (var i = 0, item; (item = itemsArray[i]); ++i) {
(itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
}
return itemsMap;
}
function sortByKeys(itemsArray, sortingArr) {
var itemsMap = createItemsMap(itemsArray), result = [];
for (var i = 0; i < sortingArr.length; ++i) {
var key = sortingArr[i];
result.push([itemsMap[key].shift(), key]);
}
return result;
}
See http://jsfiddle.net/eUskE/
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
var found = false;
for(var j=0; j < itemsArray.length && !found; j++) {
if(itemsArray[j][1] == sortingArr[i]) {
sortedArray.push(itemsArray[j]);
itemsArray.splice(j,1);
found = true;
}
}
}
http://jsfiddle.net/s7b2P/
Resulting order: Bob,Jason,Henry,Thomas,Anne,Andrew
In case you get here needing to do this with an array of objects, here is an adaptation of #Durgpal Singh's awesome answer:
const itemsArray = [
{ name: 'Anne', id: 'a' },
{ name: 'Bob', id: 'b' },
{ name: 'Henry', id: 'b' },
{ name: 'Andrew', id: 'd' },
{ name: 'Jason', id: 'c' },
{ name: 'Thomas', id: 'b' }
]
const sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Object.keys(itemsArray).sort((a, b) => {
return sortingArr.indexOf(itemsArray[a].id) - sortingArr.indexOf(itemsArray[b].id);
})
let a = ['A', 'B', 'C' ]
let b = [3, 2, 1]
let c = [1.0, 5.0, 2.0]
// these array can be sorted by sorting order of b
const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))
const sortBy = (a, b, c) => {
const zippedArray = zip([a, b, c])
const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])
return zip(sortedZipped)
}
sortBy(a, b, c)
For getting a new ordered array, you could take a Map and collect all items with the wanted key in an array and map the wanted ordered keys by taking sifted element of the wanted group.
var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
result = sortingArr.map(k => (map.get(k) || []).shift());
console.log(result);
I hope that I am helping someone, but if you are trying to sort an array of objects by another array on the first array's key, for example, you want to sort this array of objects:
const foo = [
{name: 'currency-question', key: 'value'},
{name: 'phone-question', key: 'value'},
{name: 'date-question', key: 'value'},
{name: 'text-question', key: 'value'}
];
by this array:
const bar = ['text-question', 'phone-question', 'currency-question', 'date-question'];
you can do so by:
foo.sort((a, b) => bar.indexOf(a.name) - bar.indexOf(b.name));
This is what I was looking for and I did for sorting an Array of Arrays based on another Array:
It's On^3 and might not be the best practice(ES6)
function sortArray(arr, arr1){
return arr.map(item => {
let a = [];
for(let i=0; i< arr1.length; i++){
for (const el of item) {
if(el == arr1[i]){
a.push(el);
}
}
}
return a;
});
}
const arr1 = ['fname', 'city', 'name'];
const arr = [['fname', 'city', 'name'],
['fname', 'city', 'name', 'name', 'city','fname']];
console.log(sortArray(arr,arr1));
It might help someone
I had to do this for a JSON payload I receive from an API, but it wasn't in the order I wanted it.
Array to be the reference array, the one you want the second array sorted by:
var columns = [
{last_name: "last_name"},
{first_name: "first_name"},
{book_description: "book_description"},
{book_id: "book_id"},
{book_number: "book_number"},
{due_date: "due_date"},
{loaned_out: "loaned_out"}
];
I did these as objects because these will have other properties eventually.
Created array:
var referenceArray= [];
for (var key in columns) {
for (var j in columns[key]){
referenceArray.push(j);
}
}
Used this with result set from database. I don't know how efficient it is but with the few number of columns I used, it worked fine.
result.forEach((element, index, array) => {
var tr = document.createElement('tr');
for (var i = 0; i < referenceArray.length - 1; i++) {
var td = document.createElement('td');
td.innerHTML = element[referenceArray[i]];
tr.appendChild(td);
}
tableBody.appendChild(tr);
});
let sortedOrder = [ 'b', 'c', 'b', 'b' ]
let itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
a.itemsArray(function (a, b) {
let A = a[1]
let B = b[1]
if(A != undefined)
A = A.toLowerCase()
if(B != undefined)
B = B.toLowerCase()
let indA = sortedOrder.indexOf(A)
let indB = sortedOrder.indexOf(B)
if (indA == -1 )
indA = sortedOrder.length-1
if( indB == -1)
indB = sortedOrder.length-1
if (indA < indB ) {
return -1;
} else if (indA > indB) {
return 1;
}
return 0;
})
This solution will append the objects at the end if the sorting key is not present in reference array
const result = sortingArr.map((i) => {
const pos = itemsArray.findIndex(j => j[1] === i);
const item = itemsArray[pos];
itemsArray.splice(pos, 1);
return item;
});
this should works:
var i,search, itemsArraySorted = [];
while(sortingArr.length) {
search = sortingArr.shift();
for(i = 0; i<itemsArray.length; i++) {
if(itemsArray[i][1] == search) {
itemsArraySorted.push(itemsArray[i]);
break;
}
}
}
itemsArray = itemsArraySorted;
You could try this method.
const sortListByRanking = (rankingList, listToSort) => {
let result = []
for (let id of rankingList) {
for (let item of listToSort) {
if (item && item[1] === id) {
result.push(item)
}
}
}
return result
}
with numerical sortingArr:
itemsArray.sort(function(a, b){
return sortingArr[itemsArray.indexOf(a)] - sortingArr[itemsArray.indexOf(b)];
});
This seems to work for me:
var outputArray=['10','6','8','10','4','6','2','10','4','0','2','10','0'];
var template=['0','2','4','6','8','10'];
var temp=[];
for(i=0;i<template.length;i++) {
for(x=0;x<outputArray.length;x++){
if(template[i] == outputArray[x]) temp.push(outputArray[x])
};
}
outputArray = temp;
alert(outputArray)
Use the $.inArray() method from jQuery. You then could do something like this
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();
for(var i=sortingArr.length; i--;) {
var foundIn = $.inArray(sortingArr[i], itemsArray);
newSortedArray.push(itemsArray[foundIn]);
}
Use intersection of two arrays.
Ex:
var sortArray = ['a', 'b', 'c', 'd', 'e'];
var arrayToBeSort = ['z', 's', 'b', 'e', 'a'];
_.intersection(sortArray, arrayToBeSort)
=> ['a', 'b', 'e']
if 'z and 's' are out of range of first array, append it at the end of result
this.arrToBeSorted = this.arrToBeSorted.sort(function(a, b){
return uppthis.sorrtingByArray.findIndex(x => x.Id == a.ByPramaeterSorted) - uppthis.sorrtingByArray.findIndex(x => x.Id == b.ByPramaeterSorted);
});
You can do something like this:
function getSorted(itemsArray , sortingArr ) {
var result = [];
for(var i=0; i<arr.length; i++) {
result[i] = arr[sortArr[i]];
}
return result;
}
You can test it out here.
Note: this assumes the arrays you pass in are equivalent in size, you'd need to add some additional checks if this may not be the case.
refer link
refer

Recursion logic is not working in Javascript

So I have a method that returns an object that returns referrals of a individual
function getReferredUsers(userId) {
const usersMap = {
a : ['b', 'c'],
b: ['d', 'e'],
d: ['f', 'g']
};
return usersMap[userId] || [];
}
So, in the example a directly referred b and c. While b directly referred d and e and so on.
so d and e becomes indirect referrals for a. f,g are indirect for a as d is also an indirect for a.
For direct we get 3 points for indirect we get 2.
We need to calculate total points for a.
I tried
var _opSum = 0;
function getTotalReferralBonus(userId, bonus) {
if(bonus === 0)
return 0;
let directUsers = getReferredUsers(userId);
if(directUsers.length > 0) {
for(let user of directUsers) {
_opSum = getTotalReferralBonus(user, bonus -1) + bonus;
}
}else {
_opSum += getTotalReferralBonus(userId, bonus -1);
}
return _opSum;
}
But it does not work.
What am I doing wrong ?
UPDATE
Total points that a would get is 3 + 3 (for b,c) + 2 + 2 (for d,e through b) + 1 + 1 (for f,g through d through b) = 12
You need a local variable _opSum and you need to get all bonusses from the nested Id.
function getReferredUsers(userId) {
const usersMap = {
a: ['b', 'c'],
b: ['d', 'e'],
d: ['f', 'g']
};
return usersMap[userId] || [];
}
function getTotalReferralBonus(userId, bonus) {
var _opSum = 0; // local variable
if (bonus === 0) return 0;
let directUsers = getReferredUsers(userId);
if (directUsers.length > 0) {
for (let user of directUsers) {
_opSum += getTotalReferralBonus(user, bonus - 1) + bonus; // add all instead of assignment
}
} else {
_opSum += getTotalReferralBonus(userId, bonus - 1);
}
return _opSum;
}
console.log(getTotalReferralBonus('a', 3));

compute similarities in arrays

I'm busy making filters. Now I want to compare 5 arrays which contain objects. In a computed variable I only want to have the objects that are found in all the arrays.
These are the computed variables that create the different filters (which are arrays that contain objects)
computed:
filteredOnColor () {
this.presentOnColor = []
for (var p = 0; p < this.paintings.length; p++) {
for (var i = 0; i < this.kleur.length; i++) {
if (this.kleur.length > 0 && this.paintings[p].kleur.includes(this.kleur[i])) {
this.presentOnColor.push(this.paintings[p].title)
}
}
}
},
filteredOnTechnique () {
this.presentOnTechnique = []
for (var p = 0; p < this.technique.length; p++) {
for (var i = 0; i < this.technique.length; i++) {
if (this.technique.length > 0 && this.paintings[p].technique.includes(this.technique[i])) {
this.presentOnTechnique.push(this.paintings[p].title)
}
}
}
},
filteredOnStyle () {
this.presentOnStyle = []
for (var p = 0; p < this.style.length; p++) {
for (var i = 0; i < this.style.length; i++) {
if (this.style.length > 0 && this.paintings[p].style.includes(this.style[i])) {
this.presentOnStyle.push(this.paintings[p].title)
}
}
}
},
RAW DATA
presentOnColor: [A,B,C]
presentOnStyle: [B,C,D
presentOnTechnique: [B,C,F]
presentFilter: [B,C]
You could check the arrays if the objects are included in all arrays and filter the arrays by using the common part.
var $scope = { presentOnColor: ['A', 'B', 'C'], presentOnStyle: ['B', 'C', 'D'], presentOnTechnique: ['B', 'C', 'F'] },
presentFilter = [$scope.presentOnColor, $scope.presentOnStyle, $scope.presentOnTechnique].reduce(function(a, b) {
return a.filter(function(c) {
return b.indexOf(c) !== -1;
});
});
console.log(presentFilter);
ES6
var $scope = { presentOnColor: ['A', 'B', 'C'], presentOnStyle: ['B', 'C', 'D'], presentOnTechnique: ['B', 'C', 'F'] },
presentFilter = [$scope.presentOnColor, $scope.presentOnStyle, $scope.presentOnTechnique]
.reduce((a, b) => a.filter(c => b.includes(c)));
console.log(presentFilter);
Here is very nicer more efficient way of solving the issue. I assumed A, B, C as the characters in he array. If this is happened to be the object give me properties of the object. If you get the idea then its okay.
// Given input as these 3 arrays
const presentOnColor = ['A', 'B', 'C']
const resentOnStyle = ['B', 'C', 'D'];
const presentOnTechnique = ['B', 'C', 'F'];
// Expected outcome
// const presentFilter = ['B', 'C'];
const arrayMap = [
...presentOnColor,
...resentOnStyle,
...presentOnTechnique
].reduce((object, item) => {
object[item] = (object[item] || 0) + 1;
return object;
}, {});
const presentFilter = Object.keys(arrayMap).filter(item => arrayMap[item] === 3);
console.log('presentFilter: ', presentFilter);

why is this removeDuplicate not working?

I making a function that simply removes duplicate strings, so there are only unique strings left:
var d = ['a','b','B','C','d','e','f','e'];
d.length; //8
function removeDuplicates(data) {
var i, j, a, b;
for(i = 0; i < data.length - 1; i++) {
a = data[i];
for(j = i; j < data.length; j++) {
b = data[j];
if (a.toLowerCase() == b.toLowerCase()) {
data.splice(j, 1);
}
}
}
}
removeDuplicates(d)
d.length; //4 ????
There were only two duplicates, Only B, e should have gotten removed.
but I get this:
["b", "C", "e", "e"]
Your issue is coming from the fact that any time i === j you'll have a match, and it'll be removed. In your inner loop, just put a check so that you only do your "remove them if they're equal" in situations where i !== j
Also, as nnn noted in the comments, splicing will mess up the index. The cleanest way to do this is with a filter and an every.
Updated solution below:
var d = ['a', 'b', 'B', 'C', 'd', 'e', 'f', 'e'];
var e = ['e','e','e','e'];
// d.length; //8
function removeDuplicates(data) {
const noDuplicates = data.filter((letter, ogIndex) => {
return data.every((innerLetter, innerIndex) => {
if (ogIndex < innerIndex) {
const check = letter.toLowerCase() !== innerLetter.toLowerCase();
return check;
} else {
return true;
}
})
})
return noDuplicates
}
console.log(removeDuplicates(d));
// ["a", "B", "C", "d", "f", "e"]
console.log(removeDuplicates(e));
// ["e"]
With ES6/ES2015, a simple way of getting a list of unique items is to use the new Set data type.
To "unique"-ify an array, just convert it to a set and then back to an array. i.e.
[...new Set(originalArray)]
(Update: My answer originally used Array.from(S_E_T) to convert the set back to an array. I have now changed it to [...S_E_T] to do that conversion.)
To do the same in a case-insensitive manner, follow the same logic, but just convert each original array element to its lowercase equivalent before converting that whole array to the set.
To do keep only the first instance of a string of any case (e.g. to keep 'cAt' from ['cAt', 'CaT'] instead of just the all-lowercased 'cat'), first perform the case-insensitive search as above, then get the index of each unique lowercase element from the lowercased un-uniqified original array, then use that index to retrieve the whichever-cased element from the original-cased un-uniqified original array.
const show = msg => {console.log(JSON.stringify(msg))};
const f = (arr) => {
const arrLC = arr.map(x => x.toLowerCase(x));
return [...new Set(arrLC)].map(x => arr[arrLC.indexOf(x)])
};
const d1 = ['a','b','B','C','d','e','f','e'];
const d2 = ['e', 'e', 'e', 'e', 'e'];
show(d1);
show([...new Set(d1)]);
show([...new Set(d1.map(x => x.toLowerCase(x)))]);
show(f(d1));
show('------');
show(d2);
show([...new Set(d2)]);

Categories