This is new question that is rewritten using javascript/jQuery of this thread because i can't do this in MySQL directly query.
MySQL Select id from to and exclude beginning and ending id
So question is simple:
I have array that have received from MySQL query into javascript array:
var array = ["m2", "1", "2", "11", "12", "m4", "m3", "m5", "17", "m1"];
And need function that accept parameter from what array value to show. For example:
function showCategories(marker){
}
So in above example if i call showCategories("m2"); i need to get this:
1
2
11
12
If i call showCategories("m5"); i need to get this:
17
I im currently trying to substr and find index of begin "m2" in first example and find last m index (that is m4) and remove other items from array..is there simple way?
Find the index of your marker, slice everything after it, then find the first "m" index in that array and slice up to it. All that's left is the numbers in between.
var array = ["m2", "1", "2", "11", "12", "m4", "m3", "m5", "17", "m1"];
function showCategories(marker){
let start = array.indexOf(marker);
if (start === -1) return [];
let slicedArray = array.slice(start + 1);
let end = slicedArray.findIndex(val => val.startsWith("m"));
return slicedArray.slice(0, end);
}
console.log(showCategories("m2"));
console.log(showCategories("m5"));
var array = ["m2", "1", "2", "11", "12", "m4", "m3", "m5", "17", "m1"];
function showCategories(marker) {
let currentCat = 'n';
return array.reduce((obj, item) => {
if (item.indexOf("m") === -1) {
obj[currentCat].push(item);
} else {
currentCat = item;
obj[currentCat] = [];
}
return obj;
}, {})[marker] || [];
}
console.log(showCategories("m2"));
console.log(showCategories("m5"));
Logic process
As you can see, I am using reduce and detecting if the value in the item contains an m which would indicate a new "category".
Then, I stuff all the values following the new category into an array until another category, again containing m, shows up.
Hope this helps.
Well I think you could loop through to find the index needed and store the result into a subarray.
One way would be to loop until you find the "m2" by doing:
function showCategories(find)
{
let returnArray = [];
let start = null;
if (array.includes(find) //checks if the element exists
{
for(int i = 0; i < array.length; i++)
{
if (start == null && array[i] == "m2") //looks for element
{
start = i;
}
else if(isNaN(Number(array[i]))) //pushes element into array
{
returnArray.push(array[i]);
}
else if(start != null && !isNaN(Number(array[i]))) //breaks if element after find is not an int
{
break;
}
}
}
return returnArray;
}
I haven't tested this, but something along these lines would work.
Related
I am trying to find the first 100 items in a very large array that match a condition and I'd prefer to end the loop once I've found those 100 for efficiency sake, since the method for matching the items is expensive.
The problem is that doing:
const results = largeArray.filter(item => checkItemValidity(item)).slice(0, 100);
will find all the results in the large array before returning the first 100, which is too wasteful for me.
And doing this:
const results = largeArray.slice(0, 100).filter(item => checkItemValidity(item));
could return less than 100 results.
Please what's the most efficient way of doing this?
Rather than putting a conditional and break inside a for loop, just add the extra length check in the for condition itself
const data = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"],
isValid = n => !(n%2),
res = [],
max = 5;
for (let i = 0; i < data.length && res.length < max; i++) {
isValid(data[i]) && res.push(data[i]);
}
console.log(res)
There are several array methods that will exit early Array.some, Array.every, Array.find, Array.findIndex
You can use them to stop the iteration when you need.
Example using Array.find
const data = [-1,-6,-6,-6,1,-2,2,3,4,-5,5,6,7,-8,8,9,-10,10,11,-1,2,3,4,5,-6,7,8,-9,10,11,];
const first10 = [];
data.find(item => (item > 0 && first10.push(item), first10.length >= 10));
console.log(first10 +"");
You ocul take a generator function and exit of the wanted length is found.
function* getFirst(array, fn, n) {
let i = 0;
while (i < array.length) {
if (fn(array[i])) {
yield array[i];
if (!--n) return;
}
i++;
}
}
const
expFn = x => x % 2 === 0,
array = [2, 4, 5, 1, 3, 7, 9, 10, 6, 0];
console.log(...getFirst(array, expFn, 4));
The most efficient way would be to use a for construct instead of a function and then break out when you have reached your limit.
const results = []
for (const item of largeArray) {
// End the loop
if(results.length === 100) break
// Add items to the results
checkItemValidity(item) && results.push(item)
}
console.log(results)
You can use something like this. I.e. Finding the first 5 odd numbers
var data = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"]
var filterData = [];
for (let i = 0; i < data.length; i++) {
if (data[i] % 2 === 0) {
filterData.push(data[i]);
}
// Track count console.log(i)
if (filterData.length === 5)
break;
}
console.log(filterData)
You would need to do a standard "for" loop as filter function returns a new array of the given array so here is how I would approach this:
let largeArray = ["foo", "bar", "foo", "bar"]
let validateArray = ["foo"]
let newArray = []
for (let item of largeArray){
//change number to how many items needed
if (newArray.length === 2){
console.log(newArray)
// Output would be ["foo", "foo"]
break;
}
// If you have a custom function to return true or false replace here
if (validateArray.includes(item)){
newArray.push(item);
}
}
If you are not returning strings you might need to create a custom function to return true or false depending on how you would define a validate data
I'll recommend you use findIndex, the problem with the some and every is that if the array is empty it will return true
Reference: Why does Array.prototype.every return true on an empty array?
I'm going to assume that what is expensive is the function that you are using to filter items in the array, not the actual iteration.
In that case, I would recommend using the array objects .reduce() method. Inside the function you pass to it, you can check whether your accumulator is already large enough. If it isn't, then you can conditionally add to it.
const results = largeArray.reduce(( accumulator , item )=> {
if (accumulator.length <= 100) {
if (checkItemValidity(item)) {
accumulator.push(item)
}
}
return accumulator
}, [])
I need to split an array into N number of arrays based on searching for an element from another array.
consider this scenerio
var test = ["1","2","3","env","6","7","8","uat","2344","wersdf","sdfs"];
var test2=["env","uat"];
now I want a map like
{
env:["6","7","8"],
uat:["2344","wersdf","sdfs"]
}
Note that the array items in test2 and test1 is dynamic.But two test2 values will not be coming one after another in the test array, there will be some items between it.
You could do with Array#Reduce
First iterate the test2 array and match the index of test
Then use the forloop with starting value ind+1 .it will target the next argument of delimiter
After pass the value to array using acc[b].push()
Then detect next delimiter using test2.indexOf(test[i]) == -1 on else condition.That time you need to break the statement.Then again start the second argument of test2
function maper(test, test2) {
return test2.reduce((acc, b) => {
let ind = test.indexOf(b); //detect starting index of delimiter
if (ind > -1) {
acc[b] = acc[b] || [];
for (var i = ind+1; i < test.length; i++) {
if (test2.indexOf(test[i]) == -1) { //detet next delimiter reach
acc[b].push(test[i])
}else{
break;
}
}
}
return acc
}, {})
}
var test = ["1", "2", "3", "env", "6", "7", "8", "uat", "2344", "wersdf", "sdfs"];
var test2 = ["env", "uat"];
console.log(maper(test, test2))
var test = ["1","2","3","env","6","7","8","uat","2344","wersdf","sdfs"];
var test2=["env","uat"];
var indexArray = [];
test2.map(key=>{
var index = test.indexOf(key);
indexArray.push(index);
})
var obj = {};
for(var i = 0; i<indexArray.length; i++){
var part = test.slice(indexArray[i]+1, indexArray[i+1]);
obj = {...obj,[test2[i]]: [ ...part]};
}
console.log("obj = ", obj);
I have a table of data that is rendered from an object. Specifically, each row of the table is a value from the array.
I need to be able to move the object up or down in the array, depending on the button clicked.
var obj = [{
"RuleDetailID": "11624",
"AttributeValue": "172",
"Value": "Account Manager",
"IsValueRetired": "0"
}, {
"RuleDetailID": "11626",
"AttributeValue": "686",
"Value": "Agent",
"IsValueRetired": "0"
}, {
"RuleDetailID": "11625",
"AttributeValue": "180",
"Value": "Analyst",
"IsValueRetired": "0"
}, {
"RuleDetailID": "11629",
"AttributeValue": "807",
"Value": "Individual Contributor",
"IsValueRetired": "0"
}, {
"RuleDetailID": "11627",
"AttributeValue": "690",
"Value": "Senior Agent",
"IsValueRetired": "0"
}];
// Exmaple only, just rendering a table
function renderExample() {
var table = '';
for (var key in obj) {
table += "<tr><td>" + obj[key].Value + "</td><td>Move Up</td><td></td><td>Move Down</td></tr>";
}
return table;
}
// Move the object in the array up or down
function move(value, positionChange) {
// On run, move the object in the array up or down respectivly.
}
<table>
<tbody id="example">
<script>
document.write(renderExample())
</script>
</tbody>
</table>
Can this be done with something like lodash or is it more of a manual approach? I tried by getting the index of the clicked item and then doing +1 or -1 accordingly to give me the new index. However, I wasn't sure what to do at that point since another item would already exist at that index.
How can I go about achieving this? Not looking for a jQuery approach, javascript or a library such as lodash only.
You can use array.splice twice, first to remove the item you want to move, and then to insert it into the new position
var data = [1,2,3,4,5];
function moveItem(from, to) {
// remove `from` item and store it
var f = data.splice(from, 1)[0];
// insert stored item into position `to`
data.splice(to, 0, f);
}
moveItem(0, 2);
console.log(data);
You can also use an old-school swap mechanism:
function move(value, positionChange) {
// On run, move the object in the array up or down respectivly.
for (var i = 0; i < obj.length; i++) {
if (obj[i].RuleDetailID == positionChange) {
var newIndex = value === 'up' ? i - 1 : i + 1;
if (newIndex >= obj.length || newIndex < 0) return;
var temp = obj[i];
obj[i] = obj[newIndex];
obj[newIndex] = temp;
document.getElementById('example').innerHTML = renderExample();
}
}
}
var item = {"mtyp":2,"mtr":3,"qnt":51,"unt":"pint","nts":"cvbbcv"}
var data = [{"mtyp":"2","mtr":"2","qnt":"54","unt":"ml","nts":"ngvjn"},{"mtyp":"2","mtr":"3","qnt":"51","unt":"pint","nts":"cvbbcv"}]
output should be:
var data = [{"mtyp":"2","mtr":"2","qnt":"54","unt":"ml","nts":"ngvjn"}]
You can use below script that I have written to meet your requirement.
I am assuming that your JSON object will have similar key names at both end, if not then let me know I will update the script for you.
Your desired result will be available in resultdata.
<script type="text/javascript">
var item = { "mtyp": 2, "mtr": 3, "qnt": 51, "unt": "pint", "nts": "cvbbcv" }
var data = [{ "mtyp": "2", "mtr": "2", "qnt": "54", "unt": "ml", "nts": "ngvjn" }, { "mtyp": "2", "mtr": "3", "qnt": "51", "unt": "pint", "nts": "cvbbcv" }]
// Holds the result data.
var resultdata = [{}];
// Remove initialized result set.
resultdata.pop();
// Variable to hold comparison value.
var hasMatch = false;
// Loop through data values.
for (var index = 0; index < data.length; ++index) {
// Fetch current item.
var individualData = data[index];
// Compare item values with individual data values.
if (item.mtyp == individualData.mtyp &&
item.mtr == individualData.mtr &&
item.qnt == individualData.qnt &&
item.unt == individualData.unt &&
item.nts == individualData.nts) {
hasMatch = true;
}
else {
hasMatch = false;
}
// If then is no match then add to the result.
// ResultData will hold all the values that are not present in item.
if (!hasMatch)
{ resultdata.push(individualData); }
}
</script>
While the question is quite unclear, if you like to get a new array or an in situ (in place) solution, and despite some values does not match type wise, like
qnt: 51
and
qnt: "51"
I suggest to use a combination of Array#filter for the array itself and Object.keys with Array#every for checking all properties and get all items who not match.
var item = { mtyp: 2, mtr: 3, qnt: 51, unt: "pint", nts: "cvbbcv" },
data = [{ mtyp: "2", mtr: "2", qnt: "54", unt: "ml", nts: "ngvjn" }, { mtyp: "2", mtr: "3", qnt: "51", unt: "pint", nts: "cvbbcv" }];
data = data.filter(function (a) {
return !Object.keys(item).every(function (k) {
return a[k] == item[k];
});
});
console.log(data);
I have got a fruits array as shown below
var fruits = [
{
"buyprice": "10",
"sellprice": "11",
"name": "pomogranate"
},
{
"buyprice": "10",
"sellprice": "11",
"name": "apple"
},
{
"buyprice": "12",
"sellprice": "13",
"name": "orange"
},
{
"buyprice": "14",
"sellprice": "15",
"name": "apple"
}
]
I want to find out the total counts of apple present in the array
and the buy price and sellprice of the first element of the apple present in the array (not the last element)
I have tried it this way
function findnumberofaccourences(fruits, apple) {
var a = 0;
var buyprice;
var sellprice
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
if (name == apple) {
a++;
}
}
var p = { count: a, buyprice: buyprice, sellprice: sellprice };
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
But when i run this i am getting the result as (the buyprice and sellprice of apple's last element , where as i need apples first element )
{"count":2,"buyprice":"14","sellprice":"15"}
This is my fiddle
http://jsfiddle.net/thkc0fpk/2/
could you please elt em know how to achive this
A few things:
As Hacketo said, only grab the prices when a == 0.
Also, only grab the price for apples, rather than all fruit.
Calling the argument giving the fruit name to find apple is a bit misleading (since it could contain the string pear). Perhaps fruitName or similar instead?
Here's a minimal-changes example:
function findnumberofaccourences(fruits, fruitName) {
var a = 0;
var buyprice;
var sellprice;
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
if (name == fruitName) { // Only apples
if (a == 0) { // Only the first
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
}
a++;
}
}
var p = {
count: a,
buyprice: buyprice,
sellprice: sellprice
};
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
You can also simplify a fair bit, using the more-modern forEach and using the object you're going to return directly:
function findnumberofaccourences(fruits, fruitName) {
var p = {
count: 0,
buyprice: undefined,
sellprice: undefined
};
fruits.forEach(function(fruit) {
if (fruit.name == fruitName) {
if (p.count == 0) {
p.buyprice = fruit.buyprice;
p.sellprice = fruit.sellprice;
}
p.count++;
}
});
return p;
}
var result = findnumberofaccourences(fruits, 'apple');
alert(JSON.stringify(result));
You can filter apples first into an array, then retrieve the first element of this array to get the data you need.
var apples = fruits.filter(function (fruit) {
return fruit.name === 'apple';
});
var p = {
count: apples.length,
buyprice: apples[0].buyprice,
sellprice: apples[0].sellprice
};
Just reverse the array first
var price = {
count: 0
};
fruits.reverse().forEach(function (fruit) {
if (fruit.name === "apple") {
price.count++;
price.buyprice = fruit.buyprice;
price.sellprice = fruit.sellprice;
}
})
console.log(price)
// restore original order in fruits array (if you are going to use it)
fruits.reverse();
Note that this will reverse your array in place, so you'll need to do a fruits.reverse() once again to get back the fruits array elements in the original order, if you are going to use fruits further down the flow. (Thanks aduch)
Well your code does not work as you expect, your example work only because apple is the last element of the array.
you need to update your for loop like this
for (var i = 0; i < fruits.length; i++) {
var name = fruits[i].name;
if (name == apple) {
if ( a === 0){
buyprice = fruits[i].buyprice;
sellprice = fruits[i].sellprice;
}
a++;
}
}
It will update buyprice and sellprice only the first time for the first apple
Your orignal code was updating buyprice and sellprice for each element of your array