ramda ifElse with props - javascript

I have the following object
const d = {
a: 1,
b: 2,
c: 3,
}
What a I want to do is something like this:
const type = R.ifElse(R.isEmpty(R.prop('a')), "company", "personal")(d)
The equivalent in pure javascript would be
const type = d.a ? "personal" : "company"
How can I do this with ramda?

(Disclaimer: I have literally no experience with Ramda.js, I just looked it up and tried out a little bit. There may be a better solution)
You can use R.always instead of the strings, as it expects functions there. For checking if the object has a property you can use R.has
const d = {
a: 1,
b: 2,
c: 3,
}
const x = R.ifElse(R.has('a'), R.always("company"), R.always("personal"))(d)

Related

How to get the difference between two Immutable.js Map?

I have two immutable map:
const first_map = Map({a: 1, b: 2)}
const second_map = Map({a: 1, b: 3)}
How to get the difference?
I should get:
Map({b: 3})
One possible approach is using Map.filter() - which is actually Collection.Keyed.filter() - on the second map with one condition: for a given element of this Map, there should be no element in another Map with the same key. For example:
const Map = Immutable.Map;
const first_map = Map({a: 1, b: 2, c: 4});
const second_map = Map({a: 1, b: 3, d: 5});
const diff = second_map.filter((v, k) => first_map.get(k) !== v);
console.log(diff.toString()); // Map { "b": 3, "d": 5 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>
Strictly speaking, one should check for has first - as Map.get(key) returns undefined if there's no such key, but there might be valid cases for Map containing undefined. Still, I'd encourage using null for such values.

Reduce Array of Objects with Dynamic Keys

This seems like it should be pretty simple but my searching hasn't turned anything up.
I have an array of objects that looks like this:
[{"A":4,"B":2},{"A":2,"B":1},{"A":3,"B":1},{"A":2,"B":1,"C":1}]
I want to flatten it down to something that looks like this (what I would think of as a reduce function):
{"A": 11, "B": 5, "C": 1}
The starting array of objects is the product of the transformation of a much larger and more complex starting object. The important detail is that the keys themselves are of arbitrary values (i.e. you might see 'D's and 'E's but the code itself needs to be blind to this). I've gotten to this point using Underscore.js and I'm hoping to find similarly clean, functional-style solution.
Get the key/value pairs and update the sum.
var data = [{ A: 4, B: 2 }, { A: 2, B: 1 }, { A: 3, B: 1 }, { A: 2, B: 1, C: 1 }],
result = data.reduce((r, o) => (Object.entries(o).forEach(([k, v]) => r[k] = (r[k] || 0) + v), r), {});
console.log(result);

How to best create an array of objects from a objects in one array that are not included in a second array [duplicate]

This question already has answers here:
JavaScript get elements from an object array that are not in another
(5 answers)
Closed 3 years ago.
I want an array that contains objects from the scrape object that are not present in the old object. The arrays I'm actually working with contains nearly 100 objects.
The code below works, but I wonder if there's a more efficient way of getting the same result?
var old = [
{a: 6, b: 3},
{a: 1, b: 1},
{a: 3, b: 3}
]
var scrape = [
{a: 1, b: 1},
{a: 5, b:5}
]
var nogood = []
var good =[]
scrape.forEach(es => {
old.forEach(e => {
if(e.a == es.a) {
nogood.push(es)
}
})
})
console.log(nogood)
nogood.forEach(main =>
good = scrape.filter(e=> e.a!=main.a)
)
console.log(good)
This is what I expect and what I'm getting:
good = {a:5, b:5}
Personally I would approach this with:
const old = [
{a: 6, b: 3},
{a: 1, b: 1},
{a: 3, b: 3}
];
const scrape = [{a: 1, b: 1}, {a: 5, b:5}];
for (const item of old) {
for (const i in scrape) {
if (JSON.stringify(item) === JSON.stringify(scrape[i])) {
scrape.splice(i, 1); //delete the previously scraped item
}
}
}
console.log(scrape); //{a: 5, b:5}
The benefits to this approach are:
You don't care what properties the objects you're comparing have,
you just care about whether they're identical.
It's fast
(comparing JSON is generally faster than traversing the objects to
compare each property).
It's more succinct to splice the scrape
array rather than adding the 'good' and 'nogood' arrays to arrive at
a filtered scrape array.
Possible deal breaker is if the objects you're comparing contain methods, in which case comparing them via JSON is not the correct approach.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
If we have arrays old and scrape to be of size M and N, respectively, all traditional approaches has the complexity of O(M * N) because you need to compare each entry within array scrape with the ones exists in array old to find out whether matches or not.
The second and more efficient approach is to create a hash table on first array, typically on bigger one (old here), and iterate over the second one (scrape here) which has the complexity of O(M + N).
If the size of M and N be as big as enough, the differences show themselves. As an example if M=100 and N=200, the former one needs to compare 20000 objects but the later one needs just 300 comparisons.
please take a look at this code:
const old = [
{a: 6, b: 3},
{a: 1, b: 1},
{a: 3, b: 3}
]
const scrape = [
{a: 1, b: 1},
{a: 5, b:5}
]
// create hash map using built-in Javascript Map
const pair = old.map(x => [JSON.stringify(x), true])
const map = new Map(pair)
// filter those object does not exist in hash map
const good = scrape.filter(x => !map.has(JSON.stringify(x)))
console.log(good)
How about something like this?
const good = scrape.filter((sEl) => {
return !old.some(oEl => oEl.a === sEl.a);
})
This avoids the nested forEach loops and .some will return as soon as a single true condition is found, avoiding some excess searching when an element exists early in the 'old' array.
May be something like:
var old = [
{a: 6, b: 3},
{a: 1, b: 1},
{a: 3, b: 3}
]
var scrape = [
{a: 1, b: 1},
{a: 5, b:5}
]
var result = scrape.filter(s => old.findIndex(o => o.a === s.a) === -1);
console.log(result);

jQuery map selected object

I am working with JavaScript, could you help me please
Here is my problem.
I have this object:
var MyObj= [{ a: 0, b: "Zero", c: "x", d: "!" }, { a: 1, b: "One", c: "y", d: "#" }]
I want to change the element of selected object ("a" --> "id") to become like this:
var NewObj= [{ id: 0, b: "Zero", c: "x", d: "!" }, { id: 1, b: "One", c: "y", d: "#" }]
I tried to use $.map() method like this
NewObj= $.map(MyObj, function (obj) {
return { id: obj.a, b: obj.b, c: obj.c, d:obj.d };
});
Is there any better way to do this since I only change one element of object?
No need for ES6 / Object.assign, no need for jQuery:
Working Fiddle: https://jsbin.com/gosaqid/edit?js,console
function makeObj(obj){
return obj.map(function(el, i) {
el.id = i;
delete el.a;
return el;
});
}
Not unless you have a clone/copy/extend function available. One is coming up in new JavaScript, and jQuery has one, and it's not very hard writing your own. But it still isn't a walk in the park - you can't just rename a property, you need to copy and delete:
NewObj = MyObj.map(function(obj) {
var newobj = Object.assign({}, obj, {id: obj.a});
delete newobj.a;
return newobj;
});
In your example MyObj is an array of objects.
var object = {}
var array = []
var arrayOfObjects = [{}, {}, {}]
In your desired result, you have changed one of the keys of every object in the array.
Using map is a perfectly adequate way of doing this, in fact JavaScript's array has a built in map method.
var newArrayOfObjects = arrayOfObjects.map(function (obj) {
return {
id: obj.a,
b: obj.b,
c: obj.c
}
})
If you have a ton of keys this can get a little verbose so you can use $.extend, but chances are you're writing code for modern browsers so the whole thing can be written as such:
var newArrayOfObjects = arrayOfObjects.map(obj =>
Object.assign({}, obj, { id: obj.a })
)
update: as #Amadan suggests, you can also delete the old key if you need

Javascript object array initializer formatting

My IDE is visual studio 2015 with Resharper 9.2, I want the javascript object array initializer automatically formated like this
var x = [{
a: 1,
b: 2
},{
a: 3,
b: 4
}];
I want the round and square brackets together, Any ideas how can i do this?
It is always formatted like this:
var x = [
{
a: 1,
b: 2
},{
a: 3,
b: 4
}
];
You can change the formatting rules of VS as explained here.
The problem should be solved by selecting either block or smart.

Categories

Resources