StartsWith() in an array - javascript

Basically I am using the values 'hhh' to retrieve my file. I have different field starting with 'hhhh' so I cannot base my if statement on this specific field. What I would like is to to do is map and retrieve the field with hhhh...something like this
values[startWith('hhhh')]
so then I will be able to check if the field starts with hhhh and then I will be able to differentiate the field depending on the type of each field(file, text ...)
Here is what I have as an example so you can understand. It seems that I cannot inject the startsWith() inside the array like this. Any clue on how to achieve this ?
const test =Object.entries(values['hhhhh']).map((entry, key) =>( {
test: entry[0],
test2:key
}))

You were almost there, you can use an "startWidth" method, but not directly, try combining with the array method filter, it's cleaner and readable.
const values = {
FLD_STR_101: {
test: 1
},
FLD_STR_102: {
test2: 2
},
INVALID_STR_103: {
test3: 3
}
};
const startWith = (str, prefix) => {
return str.slice(0, prefix.length) === prefix;
}
const test = Object.entries(values)
.filter(([key]) => startWith(key, 'FLD_STR_'))
.map((entry, key) =>( {
test: entry[0],
test2:key
}))

An idea can be
to filter the object key that match your expectation
loop with array.forEach method on these filtered keys
doing your map method on values[filteredKey]
const values = {
FLD_STR_101: {
test: 1,
type: 'type1'
},
FLD_STR_102: {
test2: 1,
type: 'type1'
},
FLD_STR_103_NO_TYPE: {
test2: 1
},
NOTFLD_STR_102: {
test3: 1
}
};
let test = [];
Object.keys(values)
.filter(key =>  key.startsWith('FLD_STR_') && values[key]['type'])
.forEach(filteredKey => {
test = [
...test,
...Object.entries(values[filteredKey]).map((entry, key) => ({
test: entry[0],
test2: key
}))]
});
console.log(test);

Related

How can I return a dynamic data using methods in JavaScript?

I am having a variable that needs to return data according to the array of objects.
There are 3 dummies which are dynamic in such a way -->
Example:
dummy1_A, dummy1_B, dummy1_C, ...
dummy2_A, dummy2_B, dummy2_C, ...
dummy3_A, dummy3_B, dummy3_C, ...
I want to set 'fieldName' and 'text' while returning.
And this is my code. I have to use JSON.stringify to show the data I need
Also, I am using map method
let a1 = [
{
dummy1_A: 0.5526714707565221,
dummy2_A: 0.5526714707565223,
dummy3_A: 0.5526714707565224,
dummy1_B: 0.5028423429150607,
dummy2_B: 0.5028423429150605,
dummy3_B: 0.5028423429150604,
},
{
dummy1_A: 0.542947572819916,
dummy2_A: 0.4965857885945633,
dummy3_A: 0.4965857885945677,
dummy1_B: 0.4470431086251489,
dummy2_B: 0.3785646261205342,
dummy3_B: 0.3785646261205345,
},
];
let a2 = a1.map((x, i) => {
let seqStr = String(a1.entries); // I need some help here
return {
text: seqStr,
fieldName: seqStr,
};
});
// output
[
{ text: 'dummy1_A', fieldName: 'A' },
{ text: 'dummy2_A', fieldName: 'A' },
{ text: 'dummy1_B', fieldName: 'B' },
{ text: 'dummy2_B', fieldName: 'B' },
];
We can also use forEach but this also need more logic
a1.forEach(obj => {
const key = Object.keys(obj)[0];
const newKey = key[key.length - 1];
obj[newKey] = obj[key];
delete obj[key];
});
I have used console.log(JSON.stringify(a2)); Though I was using map but not got such result
let newHeaders1 = a1.map( i => {
return {
text: i,
fieldName: 'dummy1_'+i,
width: 110
};
});
Use this and create 2 more arrays with 2 and 3 respectively.
Then consolidated all the variable in an array using concat or spread operator

filter an array of objects based on an object with an array as it's property value in react

I'm trying to create a filter function that receives two arguments: an array (which is going to be filtered) and an object which is the filter criteria.
Consider the array structure as:
const items = [
{
category: "Social",
areasAffected: ["Area_01", "Area_02"],
},
{
category: "Environmental",
areasAffected: ["Area_01", "Area_02", "Area_03", "Area_04"],
}
];
and, consider the object as below:
const filters = {
category: [{ value: "Social", label: "Social" }],
areasAffected: [{ value: "Area_01", label: "Area_01" }]
}
and I have defined the filter function as:
const filterChallenges = (items, filters) => {
const filterKeys = Object.keys(filters);
return items.filter((item) => {
filterKeys.forEach((key) => {
if (!Array.isArray(item[key])) {
return item[key]
.toString()
.toLowerCase()
.includes(
filters[key].map((filterEle) =>
filterEle.value.toString().toLowerCase()
)
);
} else {
return item[key].map((arrEle) => {
arrEle
.toString()
.toLowerCase()
.includes(
filters[key].map((filterEle) =>
filterEle.value.toString().toLowerCase()
)
);
});
}
});
});
};
when I run the function, it returns an empty array. Does anybody have any suggestion?
The code itself has two issues. First, forEach doesn't return a value. You'll want to use Array.every() here if you want to require ALL of the filters to match. Otherwise you'll want to use Array.some().
Second, String.includes() doesn't take an array, but a string. Here, you'll want to use Array.every() again if you want ALL of the items of the filter array to match the value, otherwise use Array.some(). As for the else branch which handles item values which are arrays, you'll want to use Array.some() if you just want ONE of the array values to match.
const items = [
{
category: "Social",
areasAffected: ["Area_01", "Area_02"],
},
{
category: "Environmental",
areasAffected: ["Area_01", "Area_02", "Area_03", "Area_04"],
},
];
const filterChallenges = (items, filters) => {
const filterKeys = Object.keys(filters);
return items.filter((item) => {
// ALL of the filters must be matched (.every())
return filterKeys.every((filterKey) => {
if (!Array.isArray(item[filterKey])) {
const candidateValue = item[filterKey].toString().toLowerCase();
// ALL of the filter values must be included in the item value
// (.every())
return filters[filterKey].every((filterEle) =>
candidateValue.includes(filterEle.value.toString().toLowerCase())
);
}
// Value is an array, ONE element (.some()) must match ALL of the
// filter values (.every())
return item[filterKey].some((candidate) => {
const candidateValue = candidate.toString().toLowerCase();
return filters[filterKey].every((filterEle) =>
candidateValue.includes(filterEle.value.toString().toLowerCase())
);
});
});
});
};
const ret = filterChallenges(items, {
category: [{ value: "Social", label: "Social" }],
areasAffected: [{ value: "Area_01", label: "Area_01" }],
});
console.log(ret);
Additionally, if all of your values are strings, .toString() is redundant.

Removing duplicates with in an object array using angular 4

I have an array with below list of items as shown in image , I would like to remove the duplicates
[L7-LO, %L7-LO] from that array.
I have tried with the following conditions:
Scenario 1 :
this.formulalist.filter((el, i, a) => i == a.indexOf(el))
Scenario 2:
Observable.merge(this.formulalist).distinct((x) => x.Value)
.subscribe(y => {
this.formulalist.push(y)
});
Scenario 3:
this.formulalist.forEach((item, index) => {
if (index !== this.formulalist.findIndex(i => i.Value == item.Value))
{
this.formulalist.splice(index, 1);
}
});
None of the three scenarios above were able to remove the duplicates from that array. Could any one please help on this query?
angular is not necessary use vanillajs
filter the elements with only one occurrence and add to the new list the first occurrence
let newFormulalist = formulalist.filter((v,i) => formulalist.findIndex(item => item.value == v.value) === i);
Try populating a new array without duplicates. Assign the new array later to formulalist.
newArr = []
this.formulalist.forEach((item, index) => {
if (this.newArr.findIndex(i => i.Value == item.Value) === -1)
{
this.newArr.push(item)
}
});
this.formulalist = this.newArr
EDIT
Looking at the answer above, the solution seems so outdated. A better approach would have been to use an Array.filter() than a Array.forEach().
But, having a better solution would be nice, now when I see this question, I feel findIndex() not to be a good approach because of the extra traversal.
I may have a Set and store the values in the Set on which I want to filter, If the Set has those entries, I would skip those elements from the array.
Or a nicer approach is the one that is used by Akitha_MJ, very concise. One loop for the array length, an Object(Map) in the loop with keys being the value on which we want to remove duplicates and the values being the full Object(Array element) itself. On the repetition of the element in the loop, the element would be simply replaced in the Map. Later just take out the values from the Map.
const result = Array.from(this.item.reduce((m, t) => m.set(t.name, t), new Map()).values());
Hope this works !!
// user reduce method to remove duplicates from object array , very easily
this.formulalist= this.formulalist.reduce((a, b) => {
if (!a.find(data => data.name === b.name)) {
a.push(b);
}
return a;
}, []);
// o/p = in formulalist you will find only unique values
Use a reducer returning a new array of the unique objects:
const input = [{
value: 'L7-LO',
name: 'L7-LO'
},
{
value: '%L7-LO',
name: '%L7-LO'
},
{
value: 'L7-LO',
name: 'L7-LO'
},
{
value: '%L7-LO',
name: '%L7-LO'
},
{
value: 'L7-L3',
name: 'L7-L3'
},
{
value: '%L7-L3',
name: '%L7-L3'
},
{
value: 'LO-L3',
name: 'LO-L3'
},
{
value: '%LO-L3',
name: '%LO-L3'
}
];
console.log(input.reduce((acc, val) => {
if (!acc.find(el => el.value === val.value)) {
acc.push(val);
}
return acc;
}, []));
if you are working using ES6 and up, basic JS using map and filter functions makes it easy.
var array = [{value:"a"},{value:"b"},{value:"c"},{value:"a"},{value:"c"},{value:"d"}];
console.log(array.filter((obj, pos, arr) => {
return arr.map(mapObj => mapObj["value"]).indexOf(obj["value"]) === pos;
}));
Filtering for unique values is much faster with assigning values to some object properties - there not will be duplicates.
This approach gets better and better with every +1 member of initial array, because looping will be causing fast algorithm complications
let arr = [
{value: 'L7-LO', name: 'L7-LO'},
{value: '%L7-LO', name: '%L7-LO'},
{value: 'L7-LO', name: 'L7-LO'},
{value: '%L7-LO', name: '%L7-LO'},
{value: 'L7-L3', name: 'L7-L3'},
{value: '%L7-L3', name: '%L7-L3'},
{value: 'LO-L3', name: 'LO-L3'},
{value: '%LO-L3', name: '%LO-L3'}
];
let obj = {};
const unique = () => {
let result = [];
arr.forEach((item, i) => {
obj[item['value']] = i;
});
for (let key in obj) {
let index = obj[key];
result.push(arr[index])
}
return result;
}
arr = unique(); // for example;
console.log(arr);

Best way to separate a list into two new list based on a condition

I am looking for nice good method to split array to two new arrays based on a condition.
Lets assume we have a list containing same structure objects, the object has a bool property, lets call it condition and we want two new list where we have only the same condition elements.
const cont1 = myArray.filter((el) => el.condition)
const cont2 = myArray.filter((el) => !el.condition)
This could work I guess but I am wondering if there is better single iteration verzion of this.
One option would be to use reduce, which will functionally separate all the items in only a single iteration over the array:
const myArray = [
{ condition: true },
{ condition: true },
{ condition: false },
]
const [cont1, cont2] = myArray.reduce(([cont1, cont2], item) => {
(item.condition ? cont1 : cont2).push(item);
return [cont1, cont2];
}, [[], []]);
console.log('cont1: ', cont1);
console.log('cont2: ', cont2);
Or, less functionally but perhaps more readably, you can .push to outer variables:
const myArray = [
{ condition: true },
{ condition: true },
{ condition: false },
];
const cont1 = [];
const cont2 = [];
myArray.forEach((item) => {
(item.condition ? cont1 : cont2).push(item);
});
console.log('cont1: ', cont1);
console.log('cont2: ', cont2);
Reduce could work, but reducing onto an object, with 2 different arrays as object members:
const arr = [1,2,3];
arr.reduce((acc, next) => {
if (next % 2 === 1){
acc.odd.push(next);
} else {
acc.even.push(next);
}
return acc;
}, { odd: [], even: [] }); // { even: [2], odd: [1,3] }
You can do it in a single line like this:
myArray.forEach(el=>el.condition?cont1.push(el):cont2.push(el));

lodash: mapping array to object

Is there a built-in lodash function to take this:
var params = [
{ name: 'foo', input: 'bar' },
{ name: 'baz', input: 'zle' }
];
And output this:
var output = {
foo: 'bar',
baz: 'zle'
};
Right now I'm just using Array.prototype.reduce():
function toHash(array, keyName, valueName) {
return array.reduce(function(dictionary, next) {
dictionary[next[keyName]] = next[valueName];
return dictionary;
}, {});
}
toHash(params, 'name', 'input');
Wondering if there's a lodash short-cut.
Another way with lodash 4.17.2
_.chain(params)
.keyBy('name')
.mapValues('input')
.value();
or
_.mapValues(_.keyBy(params, 'name'), 'input')
or with _.reduce
_.reduce(
params,
(acc, { name, input }) => ({ ...acc, [name]: input }),
{}
)
You should be using _.keyBy to easily convert an array to an object.
Docs here
Example usage below:
var params = [
{ name: 'foo', input: 'bar' },
{ name: 'baz', input: 'zle' }
];
console.log(_.keyBy(params, 'name'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
If required, you can manipulate the array before using _.keyBy or the object after using _.keyBy to get the exact desired result.
Yep it is here, using _.reduce
var params = [
{ name: 'foo', input: 'bar' },
{ name: 'baz', input: 'zle' }
];
_.reduce(params , function(obj,param) {
obj[param.name] = param.input
return obj;
}, {});
This seems like a job for Object.assign:
const output = Object.assign({}, ...params.map(p => ({[p.name]: p.input})));
Edited to wrap as a function similar to OP's, this would be:
const toHash = (array, keyName, valueName) =>
Object.assign({}, ...array.map(o => ({[o[keyName]]: o[valueName]})));
(Thanks to Ben Steward, good thinking...)
This is probably more verbose than you want, but you're asking for a slightly complex operation so actual code might be involved (the horror).
My recommendation, with zipObject that's pretty logical:
_.zipObject(_.map(params, 'name'), _.map(params, 'input'));
Another option, more hacky, using fromPairs:
_.fromPairs(_.map(params, function(val) { return [val['name'], val['input']));
The anonymous function shows the hackiness -- I don't believe JS guarantees order of elements in object iteration, so callling .values() won't do.
You can use one liner javascript with array reduce method and ES6 destructuring to convert array of key value pairs to object.
arr.reduce((map, { name, input }) => ({ ...map, [name]: input }), {});
Another way with lodash
creating pairs, and then either construct a object or ES6 Map easily
_(params).map(v=>[v.name, v.input]).fromPairs().value()
or
_.fromPairs(params.map(v=>[v.name, v.input]))
Here is a working example
var params = [
{ name: 'foo', input: 'bar' },
{ name: 'baz', input: 'zle' }
];
var obj = _(params).map(v=>[v.name, v.input]).fromPairs().value();
console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
It can also solve without using any lodash function like this:
let paramsVal = [
{ name: 'foo', input: 'bar' },
{ name: 'baz', input: 'zle' }
];
let output = {};
paramsVal.forEach(({name, input})=>{
output[name] = input;
})
console.log(output);

Categories

Resources