Checking existing array have given value or not - javascript

In following code i have define empty array houseTotal, now I would like to push value inside array which is unique and not exist previously. I have use some, unique, sort filter but its pushing all the value it gets. Here is my code:
let houseTotal = [];
await rel.map((each, index) => {
if (
!isEmpty(each.house_detail) ||
!houseTotal.some(el => el === each.house_detail._id)
) {
houseTotal.push(each.house_detail._id);
}
});
return houseTotal.length;
What I have done mistake here ? Thank you.

If houseTotal is to have UNIQUE values and no duplicates.. I'm going to assume "duplicates" can be == each other and I'll use the Array.includes function
let houseTotal = [];
await rel.map((each, index) => {
if (
!isEmpty(each.house_detail) ||
!houseTotal.some(el => el === each.house_detail._id)
) {
let detail=each.house_detail._id
if(!houseTotal.includes(detail)){houseTotal.push(detail);}
}
});
return houseTotal.length;

And I got the solution, it was small mistake I have made on above code, I forgot to change object id returning from mongo to string so just added toString().
let houseTotal = [];
await rel.map((each, index) => {
if (
!isEmpty(each.house_detail) ||
!houseTotal.some(el => el === each.house_detail._id.toString())
) {
houseTotal.push(each.house_detail._id.toString());
}
});
return houseTotal.length;

Related

Issue with dictionary in React

Relatively new to React/Javascript in general so any help would be appreciated.
I currently have an application which is fetching data for multiple items from an API. buys is a list of dictionaries(called buy here) with fields asset, units and price (among other things).
buys.map(async buy => {
var data = await queryCoinGeckoAPI(buy);
var market_price = data.market_data.current_price.aud;
var price_change = data.market_data.price_change_24h_in_currency.aud;
var price_change_percentage = data.market_data.price_change_percentage_24h_in_currency.aud;
var profit = buy.units === 0 || buy.price === 0 ? 0 : market_price * buy.units - buy.price;
newDictionary[buy.asset] = {
asset: buy.asset,
market_price: market_price,
price_change: price_change,
price_change_percentage: price_change_percentage,
profit: profit
};
});
That's all fine and when I come to log newDictionary:
Hooray it works!
However, the problem comes when I'm not trying to access these values in the dictionary. If I try calling newDictionary['bitcoin'] or Object.keys(newDictionary) or even
for(let key in newDictionary) {
console.log(key);
console.log(newDictionary[key]);
}
for example I get no output.
Undefined returned
Not particularly sure why and couldn't find an answer on this online...
I chose a dictionary because I would like to be able to update my current state (I hope this is how you use the spread operator):
setBuys(
buys.map(b => {
{...b, ...newDictionary[b.asset]};
})
);
Full function in case you need it :
useEffect(() => {
const refreshData = async() => {
var d = await Promise.all(
buys.map(async buy => {
var data = await queryCoinGeckoAPI(buy);
var market_price = data.market_data.current_price.aud;
var price_change = data.market_data.price_change_24h_in_currency.aud;
var price_change_percentage = data.market_data.price_change_percentage_24h_in_currency.aud;
var profit = buy.units === 0 || buy.price === 0 ? 0 : market_price * buy.units - buy.price;
return {
asset: buy.asset,
market_price: market_price,
price_change: price_change,
price_change_percentage: price_change_percentage,
profit: profit
};
})
)
var newDictionary = {};
for (let i = 0; i < d.length; i++) {
newDictionary[d[i].asset] = d[i];
}
console.log(newDictionary);
setBuys(
buys.map(
b => {
{...b, ...newDictionary[b.asset]}
}
)
)
// toast.info('Market updated', {});
}
const interval = setInterval(() => {
refreshData();
}, 60000);
return () => clearInterval(interval);
})
Thanks!
The problem with your final setBuys call is that you're simply not returning anything from the mapper function since it's using {} braces.
You'll want
setBuys(
buys.map(
b => (
{...b, ...newDictionary[b.asset]}
)
)
)
instead (b => (, not b => {).
(I'm not even sure if dictionaries are a thing in React).
You are probably thinking of objects, perhaps that can help you with googling anything related in the future.
I think the spread operator is the culprit here, try replacing it with this (forgive the formatting):
.maps( b => {{b: newArray[b.asset]}}
Try adding to some log statements to see the acual contents of newArray, maybe it is actualy an object instead of an array.

Return array value from produce function | immer.js

I am using immer.js to perform operations on arrays in the state.
Arrays: basicRecipe and recipeBasicRecipe.
I am modifying the draft.basicRecipe in the produce function. My objective is to return the updated "draft.basicRecipe" value and store the same in temparray1.
let temparray1 = produce(state, draft => {
draft.basicRecipe = draft.basicRecipe.map(item => {
let element = draft.recipeBasicRecipes.find(e => e._id === item._id);
console.log(element);
if (element) {
item.details = item.details.map(e => {
let detail = element.details.find(d => d._id === e._id);
if (detail) {
e.rate = detail.rate;
}
return e;
});
}
return item;
});
return draft.basicRecipe;
});
console.log(temparray1);
When I return the draft I am able to see updated basicRecipe nested in output.
I am getting the below error when I try to return the array i.e draft.basicRecipe
[Immer] An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft
This code is a mess. You are using map which returns a new array but you're also trying to mutate the original draft object.
This is still unreadable and confusing, but at least by using forEach instead of map we are just mutating and not trying to do two things at once.
let temparray1 = produce(state, (draft) => {
draft.basicRecipe.forEach((item) => {
let element = draft.recipeBasicRecipes.find((e) => e._id === item._id);
if (element) {
item.details.forEach((e) => {
let detail = element.details.find((d) => d._id === e._id);
if (detail) {
e.rate = detail.rate;
}
});
}
});
});

Using filter instead of foreach

I am currently trying to execute some operations after retrieving some data, the format I am trying to achieve is an array of strings:
let cleanedData = ['foo', 'bar']
The data I receive could either be an array of objects or an array of arrays that could have empty arrays that needs to be filtered out. So for example I can receive either: let notCleanedData = [['foo'],[],[],['bar']] or this let notCleanedData = [{var: 'foo'}, {var: 'bar'}]
This is my code, it is working but I would like to improve it in a cleaner way or with ES6+ methods I have tried to use a filter function without success, any advice?
function filterInputData(notCleanedData) {
let cleanedInputData = [];
notCleanedData.forEach(input => {
if (input.length > 0) {
cleanedInputData.push(input)
}
if (input.var) {
cleanedInputData.push(input.var)
}
});
return cleanedInputData;
}
console.log(
filterInputData([['foo'],[],[],['bar']])
)
console.log(
filterInputData([{var: 'foo'}, {var: 'bar'}])
)
This is a simple one-line solution that comes to my mind without using any libraries:
const clean = (data) => data.map(item => item.var || item[0]).filter(item => item)
I tried it on the test inputs you provided:
const clean = (data) => data.map(item => item.var || item[0]).filter(item => item)
console.log(
clean([['foo'],[],[],['bar']])
)
console.log(
clean([{var: 'foo'}, {var: 'bar'}])
)
const input = [['foo'],[],[],['bar']]
const input2 = [{var: 'foo'}, {var: 'bar'}]
const clean = (data) => data && data[0].length // check type
? data.flat(1) // use new flat method if array
: (data || []).map((e) => e.var) // map objects otherwise
Here is a much cleaner approach using reduce:-
// This function assumes that the array inside the array has single value and the object inside array has only one key called var
function filterInputData(notCleanedData) {
return notCleanedData.reduce((acc, item) => {
if (item.length) acc.push(item[0]);
if (item.var) acc.push(item.var);
return acc;
}, [])
}
Hope you find this useful.
I'd bring in lodash to help here.
You can use flattenDeep to clean and flatten and map to test if the data includes objects.
Example:
function clean(data) {
return
_.chain(data)
.flattenDeep()
.map(x => {
if (x.var) {
return x.var;
}
return x;
})
.value();
}
console.log(
clean([['foo'],[],[],['bar']])
)
console.log(
clean([{var: 'foo'}, {var: 'bar'}])
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
In this situation you can use map to achieve what you want without foreach. Filter wont work since it can only remove elements from the list and not actually make any modifications to them.
function filterInputData(notCleanedData) {
let cleanedInputData = notCleanedData.map((input) => {
if (input.length > 0) {
return input;
}
if (input.var) {
return input.var;
}
}).filter(item => item !== undefined);
return cleanedInputData;
}

Don't make functions within a loop no-loop-func -React JS

I am trying to find index of array using lodash locationbar. but my react console showing some warnings. can be resolve?
let wishListData = wishList.result;
let j = 0; const jMax = wishListData.length;
for (; j < jMax; j++) {
var index = _.findIndex(products.result, function (product) {
return product.id === wishListData[j]['pid']
});
if (index !== -1) {
products.result[index]['isWishList'] = true;
}
}
Iterate over wishList.result with forEach instead of a for loop, and you'll avoid the warning:
wishListData.forEach(({ pid }) => {
const index = _.findIndex(products.result, ({ id }) => id === pid);
if (index !== -1) {
products.result[index].isWishList = true;
}
});
Note that this is a linter warning, not a Javascript error. Your code works, the linter just considers it to be confusing - better to use array methods instead of loops when possible.
Also, feel free to remove the _ library and just use built-in Javascript methods instead, if you want:
wishListData.forEach(({ pid }) => {
const product = products.result.find(({ id }) => id === pid);
if (product) {
product.isWishList = true;
}
});
Or, for an O(N) solution instead of an O(N^2) solution, figure out all pids first, then iterate over the products:
const pids = new Set(wishListData.map(({ pid }) => pid));
products.result.forEach((product) => {
if (pids.has(product.id)) {
product.isWishList = true;
}
});
You can try something like this as well:
Instead of mutating product in products.result[index]['isWishList'] = true;, you should create new object to minimize side-effect.
Also, instead of looping on wishListData, you can create a list of PIDs and just check index. If this list is created outside, you can create list of PIDs outside as well. That will reduce processing it every time
const wishListPID = wishList.result.map((x) => x.pid);
const result = products.result.map((product) => {
const isWishList = wishListPID.indexOf(product.id) !== -1;
return { ...product, isWishList }
});

Remove specific property from an array of object

I have issue with splicing item from an array object with specific property.
Here is the explanation.
delColumn($event: any, el: any) {
if ($event.target && el > -1) {
var colId: string = this.receivedData[0].value.columns[el].id;
var obj = this.receivedData[0];
obj.values.columns = obj.values.columns.filter(s => s.id != colId);
obj.values.rows.forEach(s => {
delete s.Col_1;
return s;
});
}
}
Now, My requirement is When I click on Delete Column it comes into this method and I want to delete specific column and rows associated with that.
Thanks for the help in advance.
rows=[{Col1:1,Value:1},
{Col1:1,Value:2},
{Col1:1,Value:3},
{Col1:1,Value:4}];
rowsNew=this.rows.map(x=>{
return this.objectWithoutKey(x,"Col1");
})
objectWithoutKey(object, key){
const {[key]: deletedKey, ...otherKeys} = object;
return otherKeys;
}
ngOnInit()
{
console.log(this.rows);
console.log(this.rowsNew);
}
Use filter and forEach
obj.values.columns = obj.values.columns.filter(s => s.id != "Col_1");
obj.values.rows.forEach( s => {
delete s.Col_1;
return s;
});

Categories

Resources