I have Typescript code where i want to return true if any items in 1 array are present in another array. I am new to lodash but i was looking to do this using _.some. I am not sure if this is the correct approach. The code below is returning false but i expected it to return true.
let array1 = ["test", "some", "lodash"];
let array2 = ["some", "includes"];
let condition : boolean = _.some(array1, array2);
You can use intersection function and check if it returns any items:
let condition : boolean = _.intersection(array1, array2).length > 0;
With some you have to pass a test callback as a second argument:
let condition : boolean = _.some(array1, item => array2.includes(item))
lodash was cool before plain javascript had the same methods...
let array1 = ["test", "some", "lodash"];
let array2 = ["some", "includes"];
let test = array1.some(e => array2.includes(e));
console.log(test);
Related
I want to iterate an array of strings and replace each element with another string:
let arr = ["-","-","-"]
let spaceArr = replaceStringArr.forEach(replaceDash)
const replaceDash = function(index:any, array:any){
// replace the value of each element containing "-" with " "
I have tried
return array[index] = " "
and
array[index] = " "
}
I have tried:
const replaceDash = function(index: any, array: any) {
return array[index] = " "
}
as well as:
const replaceDash = function(index: any, array: any) {
array[index] = " "
}
But I am getting a:
TypeError: Cannot create property '-' on number '0'
forEach receives the parameter currentValue first, index second, array third. You would need to modify the function as follows:
const replaceDash = function(item:any, index:any, array:any){
// replace the value of each element containing "-" with " "
if(item === "-") array[index] = " ";
}
If I were you I'd also take a look at map function, which will give you a new array and seems to be more suited to what you want in less code:
let spaceArr = replaceStringArr.map(item => item === '-' ? ' ' : item);
It seems you are misunderstanding for .forEach works and confusing it for .map.
.forEach just iterates through an array, it doesn't return anything, while .map actually returns the new modified array. If you want spaceArr to be the array with modified values, try this:
let arr = ["-","-","-"]
let spaceArr = arr.map(value => {return " "})
var fakeArray [("Potato", True),("root", false),("dog", False),("cat", True)]
var OtherFakeArray ["person","cat","dog","figg"]
var finalArrat[(String,Bool)]
I want to find any item in first array that is in second array, append it to the final, both string and bool, and then copy the rest of the items that were not found in FakeArray and also append them to finalArray while applying FALSE bool to each so they can be stored in final array, so the result should be
finalArray[("dog",false),("cat",True),("figg", False),("person",False)]
So the final array includes all entries from otherFakeArray , the ones that could be matched with fakeArray have their original bool states, while the ones that were not found get a new False state to be added to the final one.
Filter out all the contents from the fakerArray that are contained in otherFakerArray. Find out all the items that are not contained and make (_, false) tuple from it and append to the ones that are contained.
Something like this,
var result = fakeArray.filter { OtherFakeArray.contains($0.0) }
let notFoundItems = OtherFakeArray.filter { item in
!result.contains(where: { $0.0 == item })
}.map { ($0, false) }
result += notFoundItems
print(result)
And here is bit better version,
let result = OtherFakeArray.map { string in
fakeArray.first(where: { $0.0 == string}) ?? (string, false)
}
Your code review
You are not using the Swift boolean type. It should be one of true or false and cannot be True and False. Didnt you try to compile it with xcode. It should not have compiled. How did you come up with the question without actually trying anything.
Here is how your actual type should look.
let fakeArray = [("Potato", true),("root", false),("dog", false),("cat", true)]
let OtherFakeArray = ["person","cat","dog","figg"]
You can try
let res1 = fakeArray.filter { otherFakeArray.contains($0.0) }
let tem = fakeArray.map { $0.0 }
let final = otherFakeArray.filter { !tem.contains($0)}.map { ($0,false)} + res1
I am trying (in js or jquery) to filter array of objects and return array of objects that have particular property name.
I tried filter and find functions like this:
var objs = [{ a:1, }, {a:2}, {a:3}, {a:4}]
var vals = [1, 2]
function callback(obj) {
var arr = arr || []
console.log(arr)
$.each(vals, function(key, val) {
if ( val == obj.a ) {
arr.push(obj)
}
})
}
var result = objs.find(callback);
console.log(">>>", result)
Expected result is:
result = [{a:1}, {a:2}]
However it doesnt work because each iteration of find starts over and defines arr all over again.
I could ofcourse make is with two nested $.each() - one to iterate through array of objects and second to iterate through array of property values but i consider is as last option - looking for something more elegant, shorter. Do you guys have any ideas?
You could do it with a filter and indexOf.
var objs = [{ a:1, }, {a:2}, {a:3}, {a:4}]
var vals = [1, 2]
function filterByValue(source, allowedValues) {
// Return the result of the filter.
return source.filter(item => {
// Returns true when `a` is present in vals (index > -1); otherwise it returns false.
return allowedValues.indexOf(item.a) > -1;
});
}
const
filteredArray = filterByValue(objs, vals);
console.log(filteredArray)
Thijs's answer works, but will get unperformant as the vals array gets large. To get O(n) complexity, you could build a set out of the allowedValues array:
var objs = [{ a:1, }, {a:2}, {a:3}, {a:4}]
var vals = [1, 2]
function filterByValue(source, allowedValues) {
allowedValues = new Set(allowedValues)
// Return the result of the filter.
return source.filter(item => {
// Returns true when `a` is present in vals, otherwise it returns false.
return allowedValues.has(item.a);
});
}
const filteredArray = filterByValue(objs, vals);
console.log(filteredArray)
Is there any possible way in angularJs to convert this array of objects:
[{"tickets":1,"month":"june","year":2016},{"tickets":2,"month":"june","year":2015},{"tickets":3,"month":"december","year":2015}]
to an array like this:
[['tickets', 'month','year'], [1, "june",2016],[3, "june",2015],[1, "december",2015]]
Approach using Array#reduce() and Array#concat() that doesn't rely on knowing any of the property names or hard coding resultant array structure
let data = [{"tickets":1,"month":"june","year":2016},{"tickets":2,"month":"june","year":2015},{"tickets":3,"month":"december","year":2015}];
let res = data.reduce((acc, curr) => {
return acc.concat([acc[0].map((key) => curr[key])]);
}, [Object.keys(data[0])]);
console.log(res)
Sure, its pure javascript can handle
var array1 = [{"tickets":1,"month":"june","year":2016},
{"tickets":2,"month":"june","year":2015},
{"tickets":3,"month":"december","year":2015}];
var array2 = [['tickets', 'month','year']];
array1.forEach(function(item){
array2.push([item.tickets, item.month, item.year]);
})
console.log(array2);
UPDATE
More flexible way, adviced by JK_Jha
var array1 = [{"tickets":1,"month":"june","year":2016},
{"tickets":2,"month":"june","year":2015},
{"tickets":3,"month":"december","year":2015}];
var array2 = [Object.keys(array1[0])];
array1.forEach(function(item){
array2.push([item.tickets, item.month, item.year]);
})
console.log(array2);
What woudl be a simple way to reduce a string like AAA:111;BBB:222;333;444;CCC:555 to a dictionary in Swift. I have the following code:
var str = "AAA:111;BBB:222;333;444;CCC:555"
var astr = str.componentsSeparatedByString(";").map { (element) -> [String:String] in
var elements = element.componentsSeparatedByString(":")
if elements.count < 2 {
elements.insert("N/A", atIndex: 0)
}
return [elements[0]:elements[1]]
}
The code above produces an Array of Dictionaries:
[["A": "111"], ["BBB": "222"], ["UKW": "333"], ["UKW": "444"], ["CCC": "555"]]
I want it to produce
["A": "111", "BBB": "222", "UKW": "333", "UKW": "444", "CCC": "555"]
but no mater what I try, since i call the map function on an Array it seems impossible to convert the nature of the map function's result.
NOTE: The dictionary in string format is described as either having KEY:VALUE; format or VALUE; format, in which case the mapping function will add the "N/A" as being the key of the unnamed value.
Any help on this matter is greatly appreciated.
Your map produces an array of dictionaries. When you want to combine them into 1, that's a perfect job for reduce:
func + <K,V>(lhs: Dictionary<K,V>, rhs: Dictionary<K,V>) -> Dictionary<K,V> {
var result = Dictionary<K,V>()
for (key, value) in lhs {
result[key] = value
}
for (key, value) in rhs {
result[key] = value
}
return result
}
var str = "AAA:111;BBB:222;333;444;CCC:555"
var astr = str
.componentsSeparatedByString(";")
.reduce([String: String]()) {
aggregate, element in
var elements = element.componentsSeparatedByString(":")
if elements.count < 2 {
elements.insert("N/A", atIndex: 0)
}
return aggregate + [elements[0]:elements[1]]
}
print(astr)
Swift has no default operator to "combine" two Dictionaries so you have to define one. Note that the + here is not commutative: dictA + dictB != dictB + dictA. If a key exist in both dictionaries, the value from the second dictionary will be used.
This is a work for reduce:
let str = "AAA:111;BBB:222;333;444;CCC:555"
let keyValueStrings = str.componentsSeparatedByString(";")
let dictionary = keyValueStrings.reduce([String: String]()) {
aggregate, element in
var newAggregate = aggregate
let elements = element.componentsSeparatedByString(":")
let key = elements[0]
// replace nil with the value you want to use if there is no value
let value = (elements.count > 1) ? elements[1] : nil
newAggregate[key] = value
return newAggregate
}
print(dictionary)
You can also make aggregate mutable directly:
let dictionary = keyValueStrings.reduce([String: String]()) {
(var aggregate: [String: String], element: String) -> [String: String] in
let elements = element.componentsSeparatedByString(":")
let key = elements[0]
// replace nil with the value you want to use if there is no value
let value = (elements.count > 1) ? elements[1] : nil
aggregate[key] = value
return aggregate
}
This is a functional approach, but you can achieve the same using a for iteration.
The reason this is happening is because map can only return arrays. If you are using this method to parse your string, then you need to convert it to a dictionary after.
var newDict = [String:String]()
for x in astr {
for (i, j) in x {
newDict[i] = j
}
}
The current issue with your code is that map function iterates over array containing [["key:value"],["key:value"]..] and you separate it again. But it returns ["key":"value"] which you then add to your array.
Instead you can add elements[0]:elements[1] directly to a locally kept variable which will fix your problem. Something like
finalVariable[elements[0]] = elements[1]