LINQ : filter multiple string values - partial match - not full match as in multiple online examples - arrays

There are many good examples of searching multiple string values in LINQ e.g.
public static Product[] GetProducts(Guid[] prodIDs)
{
return (from p in GetProducts()
where prodIDs.Contains(p.ProductID)
select p).ToArray<Product>();
}
I have a list of Products that I need to match from a customer,
but I dont have an exact match - the Customers List Of Products contains my ProductID - but it is not exact - e.g.
Customer MyCompany
Description Description
Prod1XY Prod1
AProd2B Prod2
XXXProd3 Prod3
I thus cannot filter from the prodIDs [string array] because Prod1 does not contain Prod1XY
and thus cannot use the examples that are available.
How can I effectively change (reverse) the working examples
as to search CustomerProducts where it contains my Product Description please?
So to confirm : this is not a duplicate. The examples use the string[] x
input parameter and then searches:
where x.contains
I need help to get it : myProducts.Contains(x)
another online example modified to show the situation:
static void Main(string[] args) {
var table = new[] {
new { uid = 1 },
new { uid = 2 },
new { uid = 3 },
new { uid = 4 },
new { uid = 5 }
};
var stringarray = new[] { "1", "5", "10" };
var results = from xx in table
where table.Contains(stringarray)
select xx;
foreach (var result in results) {
Console.WriteLine("Result: " + result.uid.ToString());
}
}

It is not clear enough what you are trying to accomplish, but under assumption that you want to select all products where ProductID contains any value from specified list, it looks like that it:
public static Product[] GetProducts(string[] prodIDs)
{
return (from p in GetProducts()
where prodIDs.Any(id=>p.ProductID.Contains(id))
select p).ToArray<Product>();
}

Try this
public static Product[] GetProducts(string[] prodIDs)
{
return (
from p in GetProducts()
from q in prodIDs
where p.ProductID.IndexOf(q) > -1
select p)
.ToArray<Product>();
}

Related

Retrieve array based on ids of another array

I have two arrays of users and beams
struct User {
var id: Int
var jobTitle: String
}
struct Beams {
var isSelected = false
var id: Int
var userIds: [Int]
}
If the user selects a particular beam, all the users which are assigned to that beam will be selected of the first array. The user can select multiple beams and i am getting the data from api response, and i have to send the selected users in a post call. so i have to select all the selected users from an array of beams and on the basis of filtered ids, send that array in a post call. initially i am filtering all the beams which are selected like this
beams.filter { $0.isSelected }.compactMap { $0.userIDS }
which gives me an array of [Int]. These are the userIds which have to be sent. I somehow can't figure out how will i select these particular ids from my array of users which contains other attributes as well. contains can be used to filter one element but not a sequence. and even if i filter or take an intersection of these ids and my userArray. i am still left with a set or an array of ids. from which i'd have to generate my array, i want to keep all the other attributes as well. Any help in the right direction would be appreciated. I have something of this nature in my mind
let selectedBeamsIds = beams.filter { $0.isSelected }.compactMap { $0.userIDS }
users.append(selectedBeamsIds.compactMap { getUniqueUsersForBeams(ids: $0) } )
private func getUniqueUsersForBeams(ids: [Int]) -> [User] {
let ower = users.reduce(into: [User]()) { (result,
user) in
let filteredUserIds = ids.filter { $0 == user.id }
//result.append(use)
}
}
I also need to do this with another array of jobTitles which is like
struct JobTitle {
var jobTitle: String
var isSelected = false
}
this one is straight forward as if the users's jobTitle matches with the selected items of [String] array then select that user to be sent.
Try,
let selectedIds = beams.filter { (beams) -> Bool in
beams.isSelected
}.flatMap { (beams) -> [Int] in
beams.userIds
}
let filteredUsers = users.filter { (user) -> Bool in
selectedIds.contains(user.id)
}
1 ) Filter out selected beams
2 ) Collect all the userIds in the selected beams
3 ) Filter users by checking if the id is present in the previously collected ids.

Infinite loop on JS for

My code stays in the second for forever, testing the same category every step and decrementing every time.
I have two arrays, one of them is called categoriesToUpdate and is a list of category ids (string values) for categories that I have to update, and the other is called categories, containing all the actual category data I'm working with.
I have to test if the id value for a category that I have to update is the same as the database and if it is, decrement the attribute position of its object and update the database. But it is infinitely decrementing the bank.
let newCategory;
let name;
let position;
for(let id of categoriesToUpdate) {
for(let cat of categories) {
if(id === cat.id) {
position = cat.category.category.lastPosition - 1;
name = cat.category.category.categoryName;
newCategory = {
category: {
categoryName: name,
lastPosition: position,
}
}
cRef.child(id).update(newCategory);
}
}
}
Examples of the two arrays:
categoriesToUpdate = ['-lGz4j77...', '-uEbKO3...', ...]
and
categories = [
{
category: {
category: {
categoryName: "name",
lastPosition: "number",
}
},
id: "category id";
},
{
...
}
]
it is difficult to explain how I get the arrays, but basically, categoriesToUpdate is an array of ids that I add to my logic, I have to do update in each of these categoriesand categories is an array that has all categories of the database, comes from Firebase.
let id of categoriesToUpdate. I'm assuming categoriesToUpdate is an array of Category objects. So id is actually a Category object. To compare it should be id.id === cat.id.
Also you can try filter instead of a second loop.
Something like
var matched = categories.filter(c => c.id === id.id)[0];
Then compare matched. Nested loops are hard to read, imo.

Modify an array element after finding it in swift does not work

I wrote a model like this as an exercise :
struct Store {
var name : String
var bills : Array<Bill>
var category : Category?
}
struct Bill {
var date : String
var amount : Float
}
struct Category {
var name : String
var tags : Array<String>
}
and when I'm searching if a store already exist to add a bill to it instead of creating a new store, my code doesn't work. It acts like if the result of the search is a copy of the Array element . I would like to have a reference.
var stores : Array <Store> = Array()
for billStatment in billStatements! {
let billParts = billStatment.split(separator: ",")
if billParts.count > 0 {
let bill : Bill = Bill(date:String(billParts[0]), amount: Float(billParts[2])!)
var store : Store = Store(name:String(billParts[1]), bills: [bill], category: nil)
if var alreadyAddedStore = stores.first(where: {$0.name == String(billParts[1])}) {
alreadyAddedStore.bills.append(bill)
print("yeah found it \(alreadyAddedStore)") // the debugger breaks here so I know the "first" method is working. If I print alreadyAddedStore here I have one more element, that's fine.
} else {
stores.append(store)
}
}
}
print("\(stores.count)") // If I break here for a given store that should contains multiple elements, I will see only the first one added in the else statement.
Can anyone tell me what I am doing wrong?
As already noted, you're confusing value (struct) semantics with reference (class) semantics.
One simple fix would be the change stores to a dictionary with the name as your key:
var stores : Dictionary<String, Store> = [:]
and use it like this:
if(stores[store.name] == nil) {
stores[store.name] = store
}
else {
stores[storeName].bills.append(bill)
}

UpdateOperations embedded array

I have an structure like this:
{
_id: 123,
bs: [
{
_id: 234,
cs: [
{
_id: 456,
ds : [
{
_id: 678,
emails[
"email#gmail.com"
]
}
]
}
]
}
]
}
My classes in Morphia seems like this
#Entity
public class A {
#Id
private ObjectId id;
#Embedded
private List<B> bs;
}
public class B {
private ObjectId id;
#Embedded
private List<C> cs;
}
public class C {
private ObjectId id;
#Embedded
private List<D> ds;
}
public class D {
private ObjectId id;
#Embedded
private List<String> emails;
}
What I am trying to do is insert an email inside embedded array with Morphia without retrieve all element A and use updateFirst.
This is the query I am trying execute
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.criteria("bs.cs.id").equal(new ObjectId(cID));
query.criteria("bs.cs.ds.id").equal(dID);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.$.emails", email);
this.basicDAO.update(query, updateOps);
I also read about this post Update an item in an array that is in an array with said that
$ operator does not work "with queries that traverse nested arrays".
So I tried something like:
D d = new D(dID);
C c = new C(new ObjectId(cID));
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.field("bs.cs").hasThisElement(c);
query.field("bs.cs.ds").hasThisElement(d);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.emails", email);
this.basicDAO.update(query, updateOps);
However it still doesn't work. Any idea how solve this? The error message that I receive is cannot use the part ... to transverse the element
Based on your stand-in use case, I think you should "invert" your schema. Each document will represent a lecture and will be tagged with its theme, edition, and event:
{
"_id" : ObjectId("54da1ff0a9ce603a239c3075"),
"event" : "X0004",
"edition" : "A0002,
"theme" : "RT0005",
"votes" : 22
}
event, edition, and theme can be some kind of identifiers, and might be references to event, edition, and theme documents in other collections. To cast a vote for a particular lecture, just update it by _id:
db.test.update({ "_id" : ObjectId("54da1ff0a9ce603a239c3075") }, { "$inc" : { "votes" : 1 } })
While I don't know your full requirements, I think this is a better basic design given your example use case.

How to count number of same data in a column

I have a table:
Id Catg
1 cat01
2 cat01
3 cat01
1 cat02
2 cat02
now I want to detect number of occurance of catg01 and catg02,like in this ex, catg01 is 3 times and catg02 is 2 times,I want to count that through LINQ/ simple db query.
Pls note: cant use Where clause and hardcode Catg01/catg 02,as there can n number of category.Is it possible to detect? if yes then pls help.
SELECT Catg, COUNT(*)
FROM myTable GROUP BY Catg
Select Catg, Count(*) From TableName Group By CatG
For the LINQ Version. Imagine a Class
class Table
{
public int ID { get; set; }
public string CatG { get; set; }
}
Then if you had a list of that class, you could query it as follows
List<Table> y = new List<Table>();
y.Add(new Table() { ID = 1, CatG = "a" });
y.Add(new Table() { ID = 2, CatG = "a" });
y.Add(new Table() { ID = 3, CatG = "a" });
y.Add(new Table() { ID = 4, CatG = "b" });
y.Add(new Table() { ID = 5, CatG = "b" });
var query = y.GroupBy(table => table.CatG);
// Iterate over each IGrouping in the collection.
foreach (var item in query)
{
Console.WriteLine("CatG: {0} Number of Items: {1}", item.Key, item.Count());
}

Resources