Efficient way to search object from list of object in c# - c#-4.0

I have a list which contains more than 75 thousand object. To search item from list currently I am using following code.
from nd in this.m_ListNodes
where
nd.Label == SearchValue.ToString()
select
nd;
Is this code is efficient?

How often do you need to search the same list? If you're only searching once, you might as well do a straight linear search - although you can make your current code slightly more efficient by calling SearchValue.ToString() once before the query.
If you're going to perform this search on the same list multiple times, you should either build a Lookup or a Dictionary:
var lookup = m_ListNodes.ToLookup(nd => nd.Label);
or
var dictionary = m_ListNodes.ToDictionary(nd => nd.Label);
Use a dictionary if there's exactly one entry per label; use a lookup if there may be multiple matches.
To use these, for a lookup:
var results = lookup[SearchValue.ToString()];
// results will now contain all the matching results
or for a dictionary:
WhateverType result;
if (dictionary.TryGetValue(SearchValue.ToString(), out result))
{
// Result found, stored in the result variable
}
else
{
// No such item
}

No. It would be better if you used a Dictionary or a HashSet with the label as the key. In your case a Dictionary is the better choice:
var dictionary = new Dictionary<string, IList<Item>>();
// somehow fill dictionary
IList<Item> result;
if(!dictionary.TryGetValue(SearchValue.ToString(), out result)
{
// if you need an empty list
// instead of null, if the SearchValue isn't in the dictionary
result = new List<Item>();
}
// result contains all items that have the key SearchValue

Related

Searching an array of strings in a file

I have a text file say, testFile.txt and an array of strings to be searched in the file as say, ['year', 'weather', 'USD 34235.00', 'sportsman', 'ಕನ್ನಡ']. I can break the file into tokens with NodeJS natural and maybe, create a large array (~100-200x the number of entries in the string array) out of it. Then, sort both the arrays and start the search. Or, use lodash directly?
A Found result is when at least one string from the search string array is found in the text file; else, it should be considered as NotFound.
What are some of the options to implement such a search?
I could suggest using Set for large array of tokens, then iterate through the search terms array, check if the tokens set has one of those terms. If the terms array is also large, you could considers using Set for that (MDN docs for Set)
You could see the performance comparision between array and set in context of large number of elements, from this comment
Below is the demo snippet
const tokens1 = ['ಕನ್ನಡ', 'asdasd', 'zxczxc', 'sadasd', 'wqeqweqwe', 'xzczxc']
const tokens2 = ['xzczcxz', 'asdqwdaxcxzc', 'asdxzcxzc', 'wqeqwe', 'zxczcxzxcasd']
const terms = ['year', 'weather', 'USD 34235.00', 'sportsman', 'ಕನ್ನಡ']
const set1 = new Set(tokens1)
const set2 = new Set(tokens2)
const find = (tokensSet, termsArray) => {
for (const term of termsArray) {
if (tokensSet.has(term)) {
return 'Found'
}
}
return 'Not Found'
}
console.log(find(set1, terms))
console.log(find(set2, terms))

How to find the string from string array in firestore

I have a list of documents and each document has a field of a string array named "fav", it has more than 50k emails, there are almost 1000 documents and in each document's "fav" array has variable length including 50k, 20k,10, etc. I was fetching all documents
Firestore.instance.collection("save").snapshots();
through StreamBuilder
StreamBuilder(
stream: Firestore.instance.collection("save").snapshots();,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text("Loading Data.............");
else {
listdata = snapshot.data.documents;
return _buildBody(snapshot.data.documents);
}
},
)
Now How I can search my required email from each document's field "fav"? I have to perform an operation after finding the required id in the array locally.
The question is not very clear, but for my understanding, this is what you are looking for
Firestore.instance.collection('save')
.where('fav', arrayContains: 'abc#gmail.com').snapshots()
The question is not very clear, but for my understanding, you want to find one e-mail in the array field. This array is contained on each document, and all the documents are "streamed" in a collection of snapshots.
Contains Method: https://api.dartlang.org/stable/2.0.0/dart-core/Iterable/contains.html
bool contains (
Object element
)
Returns true if the collection contains an element equal to element.
This operation will check each element in order for being equal to element, unless it has a more efficient way to find an element equal to element.
The equality used to determine whether element is equal to an element of the iterable defaults to the Object.== of the element.
Some types of iterable may have a different equality used for its elements. For example, a Set may have a custom equality (see Set.identity) that its contains uses. Likewise the Iterable returned by a Map.keys call should use the same equality that the Map uses for keys.
Implementation
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}

NODE.JS: iterating over an array of objects, creating a new key if it does not exist

I am iterating over a collection of data, in my case, an array of objects. Here is a sample of 2 data points from it:
{
violation_id: '211315',
inspection_id: '268804',
violation_category: 'Garbage and Refuse',
violation_date: '2012-03-22 0:00',
violation_date_closed: '',
violation_type: 'Refuse Accumulation' },
{
violation_id: '214351',
inspection_id: '273183',
violation_category: 'Building Conditions',
violation_date: '2012-05-01 0:00',
violation_date_closed: '2012-04-17 0:00',
violation_type: 'Mold or Mildew' }
I need to create a new array of objects from this, one for each "violation_category" property. If Violation category already exists in the new array I am creating, i simply add the information to that existing category object (instead of having two "building conditions" objects for example, I would just add to an existing one).
However, I am having trouble assigning to the existing object if the current one exists (it's easy to check if it does not, but not the other way around). This is what am attempting to do currently:
if (violationCategory.uniqueCategoryName) {
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
} else {
category.violations = results[i].violation_id;
category.date = results[i].violation_date;
category.closed = results[i].violation_date_closed;
violationCategory.push(category);
}
In first condition, if this category (key) exists, I simply add to it, and in the second condition, this is where I am struggling. Any help appreciated. Thanks guys.
Just add an empty object to the key if there no object there :
violationCategory.uniqueCategoryName = violationCategory.uniqueCategoryName || {};
And only then, add the data you want to the object.
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
No condition needed.
Good luck!
Assuming that you have an input variable which is an array of objects, where the objects are looking like the objects of the question, you can generate your output like this:
var output = {};
for (var item of input) {
if (!output[item.violation_category]) output[item.violation_category] = [];
output[item.violation_category].push(item);
}
Of course you might customize it like you want.

How to list and remove duplicate values using mongoose

Following the comments on Mongoose: how to define a combination of fields to be unique?
First let's get the array of data sorted by all values which supposed to be unique.
Assuming we're talking about strings (as in this question), we can combine them to create one long string that is supposed to be unique.
Being sorted, if there are duplicate values they'll show up right after the other, so let's look for results that repeat themselves:
var previousName;
Person.find().sort('firstName lastName').exec().each(function (person) {
var name = person.firstName + person.lastName;
if (name == previousName) {
console.log(name);
person.remove();
}
previousName = name;
})

How to get from CouchDB only certain fields of certain documents for a single request?

For example I have a thousands of documents with same structure, for example:
{
"key_1":"value_1",
"key_2":"value_2",
"key_3":"value_3",
...
...
}
And I need to get, let's say key_1, key_3 and key_23 from some set of documents with known IDs, for example, I need to process only 5 documents while my DB contains several thousands. Each time I have a different set of keys and document IDs. Is it possible to get that information for a one request?
You can use a list function (see: this, this, and this).
Since you know the ids, you can then query _all_docs with the list function:
POST /{db}/_design/{ddoc}/_list/{func}/_all_docs?include_docs=true&columns=["key_1","key_2","key_3"]
Accept: application/json
Content-Length: {whatever}
{
"keys": [
"docid002",
"docid005"
]
}
The list function needs to look at documents, and send the appropriate JSON for each one. Not tested:
(function (head, req) {
send('{"total_rows":' + head.total_rows + ',"offset":' + head.offset + ',"rows":[');
var columns = JSON.parse(req.query.columns);
var delim = '';
var row;
while (row = getRow()) {
var doc = {};
for (var k in columns) {
doc[k] = row.doc[k];
}
row.doc = doc;
send(delim + toJSON(row));
delim = ',';
}
send(']}');
})
Whether this is a good idea, I'm not sure. If your documents are big, and bandwidth savings important, it might.
Yes, that’s possible. Your question can be broken up into two distinct problems:
Getting only a part of the document (in your example: key_1, key_3 and key_23). This can be done using a view. A view is saved into a design document. See the wiki for more info on how to create views.
Retrieving only certain documents, which are defined by their ID. When querying views, you cannot only specify a single ID (or rather key), but also an array of keys, which is what you would need here. Again, see the section on querying views in the wiki for explanations and examples.
Even though you only need a subset of values from a document, you may find that the system as a whole performs better if you just ask for the entire document then select the values you need from that result.
To only get the specific key value pairs you need to create a view that has view entries with a multipart key consisting of the doc id and doc item name, with value of the corresponding doc item.
So your map function would look something like:
function(doc){
for(var i = 1; i < doc.keysInDoc; i++){
var k = "key_"+i;
emit([doc._id, k], doc.[k]);
}
}
You can then use multi key lookup with each key being of the form ["docid12345", "key_1"], ["docid56789", "key_23"], etc.
So a query like:
http://host:5984/db/_design/design/_view/view?&keys=[["docid002","key_8"],["docid005","key_7"]]
will return
{"total_rows":84,"offset":67,"rows":[
{"id":"docid002","key":["docid002","key_8"],"value":"value d2_k8"},
{"id":"docid005","key":["docid005","key_12"],"value":"value d5_k12"}
]}

Resources