I am trying to use primitive code like this:
var pageSize = 100;
var startPosition = 0;
do
{
var searchResponse = client.Search<Bla>(s => s
.Index(indexName)
.Query(q => q.MatchAll()
).From(startPosition).Size(pageSize)
);
startPosition = startPosition + pageSize;
} while (true);
to page over all ingested documents. This breaks the server as the requests are too frequent I believe. I could slow things down by going to sleep for a few milliseconds, but I think this would still not be best practice.
I know there is also the concept of scrolling. How would I use this in my scenario, where I would like to act upon each page's result?
PS:
static void Main(string[] args)
{
var indexName = "document";
var client = GetClient(indexName);
var pageSize = 1000;
var numberOfSlices = 4;
var scrollObserver = client.ScrollAll<Document>("1m", numberOfSlices, s => s
.MaxDegreeOfParallelism(numberOfSlices)
.Search(search => search
.Index(indexName).MatchAll()
.Size(pageSize)
)
).Wait(TimeSpan.FromMinutes(60), r =>
{
// do something with documents from a given response.
var documents = r.SearchResponse.Documents.ToList();
Console.WriteLine(documents[0].Id);
});
}
I am familiar with the observer pattern but not sure what exactly these components mean:
"1m"
numberOfSlices
TimeSpan.FromMinutes(60)
Something along those lines seems to work:
const string indexName = "bla";
var client = GetClient(indexName);
const int scrollTimeout = 1000;
var initialResponse = client.Search<Document>
(scr => scr.Index(indexName)
.From(0)
.Take(100)
.MatchAll()
.Scroll(scrollTimeout))
;
List<XYZ> results;
results = new List<XYZ>();
if (!initialResponse.IsValid || string.IsNullOrEmpty(initialResponse.ScrollId))
throw new Exception(initialResponse.ServerError.Error.Reason);
if (initialResponse.Documents.Any())
results.AddRange(initialResponse.Documents);
var scrollid = initialResponse.ScrollId;
bool isScrollSetHasData = true;
while (isScrollSetHasData)
{
var loopingResponse = client.Scroll<XYZ>(scrollTimeout, scrollid);
if (loopingResponse.IsValid)
{
results.AddRange(loopingResponse.Documents);
scrollid = loopingResponse.ScrollId;
}
isScrollSetHasData = loopingResponse.Documents.Any();
// do some amazing stuff
}
client.ClearScroll(new ClearScrollRequest(scrollid));
What I implemented with a for loop is this:
phraseSources2 = new List<PhraseSource2>();
for (int i = 0; i < phraseSources.Count; i++)
{
var ps = phraseSources[i];
if (i != phraseSources.Count - 1)
{
var psNext = phraseSources[i + 1];
if (psNext != null &&
ps.Kanji == psNext.Kanji &&
ps.Kana == psNext.Kana &&
ps.English.Length <= psNext.English.Length)
{
i++;
ps = phraseSources[i];
}
} else
{
ps = phraseSources[i];
}
phraseSources2.Add(new PhraseSource2()
{
Kanji = ps.Kanji,
Kana = ps.Kana,
Furigana = ps.Furigana,
English = ps.English,
});
}
Previously I had been using LINQ
phraseSources2 = (List<Data1.Model.PhraseSource2>)phraseSources
.Select(x => new PhraseSource2()
{
Kanji = x.Kanji,
Kana = x.Kana,
Furigana = x.Furigana,
English = x.English,
}).ToList();
I know LINQ can do a lot but can it look forward at the next row when doing a select?
If I understand your problem correcly I wouldn't "look forward" but use GroupBy instead and group by Kanji and Kana then Select the longest English as the value in the PhraseSource2 object.
Something like this:
var phraseSource2 = phraseSources
.GroupBy(x => new {Kanji = x.Kanji, Kana = x.Kana})
.Select(g => new PhraseSource2 {
Kanji = g.Key.Kanji,
Kana = g.Key.Kana,
Furigana = g.First().Furigana,
English = g.OrderByDescending(x => x.English.Length).First().English
});
If the source collection can be accessed by index than you can use an overload to the select which gives you the current index.
var source = new[] { 'a', 'b', 'c' };
var result = source.Select((x, i) => new { Current = x, Next = source.Length > i+1 ? source[i+1] : ' '});
All you have to do is just set up a variable inside a query where you can easily retrieve next or previous value like this:
phraseSources2 = (List<Data1.Model.PhraseSource2>)phraseSources
.Select((x, y) =>
var NextKanji = (List<Data1.Model.PhraseSource2>)phraseSources.Skip(y + 1).FirstOrDefault().Kanji;
new PhraseSource2()
{
Kanji = NextKanji,
Kana = x.Kana,
Furigana = x.Furigana,
English = x.English,
}).ToList();
If you want to check some conditions before, you can do it like this:
phraseSources2 = (List<Data1.Model.PhraseSource2>)phraseSources
.Where((x, y) =>
var NextEnglish = (List<Data1.Model.PhraseSource2>)phraseSources.Skip(y + 1).FirstOrDefault().English;
x.English.Length < NextEnglish.Length)
.Select(x =>
new PhraseSource2()
{
Kanji = x.Kanji,
Kana = x.Kana,
Furigana = x.Furigana,
English = x.English,
}).ToList();
There is no built-in method, but there are third-party libraries that offer this functionality. The MoreLinq is a respected and free .NET library that offers a WindowLeft extension method, that processes a sequence into a series of subsequences representing a windowed subset of the original. So you could use it to process your phraseSources in pairs, and discard the pairs that have two equal phrases. Finally select the first phrase of the pairs that survived.
using static MoreLinq.Extensions.WindowLeftExtension;
var phraseSources2 = phraseSources
.WindowLeft(size: 2)
.Where(phrases => // phrases is of type IList<PhraseSource2>
{
if (phrases.Count == 2) // All have size 2 except from the last
{
var ps = phrases[0];
var psNext = phrases[1];
return ps.Kanji != psNext.Kanji || ps.Kana != psNext.Kana ||
ps.English.Length > psNext.English.Length;
}
else // The last is a single phrase
{
return true;
}
})
.Select(window => window[0]) // Select the first phrase
.ToList();
I have an older version of code that was doing multiple lookup. I needed some additional fields so instead i rewrote it to do a couple joins and return everything i needed at once. I imagined this would have better performance, but when testing with a stopwatch this was not the case and quite slower. Am i inadvertently doing something wrong with my query?
Old Code
// ===============================old
var watchOld = System.Diagnostics.Stopwatch.StartNew();
var def = context.FDataMLBPlayers.Where(d => d.Status.Trim().ToLower().Equals("active") && d.Position.Trim().ToLower().Equals(position.ToLower())).OrderBy(d => d.Team);
foreach (var dd in def)
{
bool addPlayer = false;
foreach (var tm in teams)
{
if (tm.Trim().Equals(dd.Team.Trim()))
{
addPlayer = true;
break;
}
}
if (!addPlayer) continue;
Player player = new Player();
player.Name = dd.FirstName.Trim() + " " + dd.LastName.Trim();
player.LastName = dd.LastName.Trim();
player.Number = dd.Jersey.HasValue ? dd.Jersey.Value : 0;
player.PlayerID = dd.PlayerID;
player.Points = 0;
player.Position = (dd.Position == null) ? "" : dd.Position.Trim();
player.Score = 0;
player.Status = "Active";//DOROC dd.CurrentStatus;
player.Team = dd.Team.Trim();
htop ht = GetOpposingTeam(dd.Team.Trim()); //another lookup
player.OpposingTeam = ht.OpposingTeam;
player.PhotoUrl = dd.PhotoUrl.Trim();
player.IsHomeTeam = ht.IsHomeTeam;
if (dd.Position != null)
{
list.Add(player);
}
}
watchOld.Stop();
var oldTime = watchOld.ElapsedMilliseconds; // 227 ms
New Code
// ========================================== new
var watchNew = System.Diagnostics.Stopwatch.StartNew();
var def2 = (from p in context.FDataMLBPlayers
join g in context.FDataMLBPlayerGames on p.PlayerID equals g.PlayerID
join t in context.FDataMLBTeams on g.OpponentID equals t.TeamID
where p.Status.Trim().ToLower().Equals("active")
&& p.Position.Trim().ToLower().Equals(position.ToLower())
&& teams.Contains(p.Team)
group new { p, g, t }
by new { p.PlayerID } into pgt
let fod = pgt.FirstOrDefault()
select new Player
{
DateTime = fod.g.DateTime.Value,
IsHomeTeam = fod.g.HomeOrAway.ToLower().Equals("home") ? true : false,
LastName = fod.p.LastName,
Name = fod.p.FirstName.Trim() + " " + fod.p.LastName.Trim(),
Number = fod.p.Jersey.HasValue ? fod.p.Jersey.Value : 0,
OpposingTeam = fod.t.Name,
PhotoUrl = fod.p.PhotoUrl,
PlayerID = fod.p.PlayerID,
Points = 0,
Position = fod.p.Position,
Score = 0,
Started = fod.g.Started.Value.Equals(1) ? true : false,
Status = fod.p.Status,
Team = fod.p.Team,
}
).ToList();
list = def2;
watchNew.Stop();
var newTime = watchNew.ElapsedMilliseconds; // 399 ms
Problem Description : I want to create jquery method from where i can convert gold weight to amount by multiplying it from gold rate f.e 50*2000=100000 and vice versa also that is Amount to Gold by dividing it from gold rate f.e 100000/2000=50
Amount=GoldWeight*GoldRate; // TOP DOWN APPROACH
GoldWeight=Amount/GoldRate; // BOTTOM UP APPROACH
But at the same if all textbox have values it should convert gold if we change amount and also amount if we change in gold value....Please help me in this..
This is the Answer
$(document).ready(function() {
$('#txtGoldConverted').focusin(function() {
var r = $('#txtAmount').val();
var q = $('#txtGoldRate').val();
if (r != "" && q != "") {
var p = r / q;
var res = p.toFixed(3);
var resRound = (Math.round(res * 100)) / 100;
$('#txtGoldConverted').val(resRound);
}
});
$('#txtGoldConverted').focusout(function() {
var p = $('#txtGoldConverted').val();
var q = $('#txtGoldRate').val();
if (p != "" && q != "") {
var r = p * q;
$('#txtAmount').val(r);
}
});
$('#txtGoldRate').focusout(function() {
var p = $('#txtGoldConverted').val();
var q = $('#txtGoldRate').val();
var r = p * q;
$('#txtamount').val(r);
});
$('#txtAmount').focusin(function() {
var p = $('#txtGoldConverted').val();
var q = $('#txtGoldRate').val();
if (p != "" && q != "") {
var r = p * q;
$('#txtAmount').val(r);
}
});
$('#txtAmount').focusout(function() {
var r = $('#txtAmount').val();
var q = $('#txtGoldRate').val();
if (r != "" && q != "") {
var p = r / q;
var res = p.toFixed(3);
var resRound = (Math.round(res * 100)) / 100;
$('#txtGoldConverted').val(res);
}
});
});
You need to use focusout() function on your both Textboxes inorder to Change one Value Based on Other
Example
$('#goldbox').focusout(function(){
var newamount;
//calculate money value based on gold
$('#moneybox').val(newamount);
});
I have an IEnumerable and I wanted to split the data across 3 columns using the following business logic. if 3 or less items, 1 item per column, anything else I wanted to divide the total items by 3 split the leftovers (either 1 or 2 items) between the first two columns. Now this is pretty ugly but it does the job. I'm looking for tips to leverage linq a little better or possibly eliminate the switch statement. Any advice or tips that improve the code are appreciated.
var numItems = items.Count;
IEnumerable<JToken> col1Items,
col2Items,
col3Items;
if(numItems <=3)
{
col1Items = items.Take(1);
col2Items = items.Skip(1).Take(1);
col3Items = items.Skip(2).Take(1);
} else {
int remainder = numItems % 3,
take = numItems / 3,
col1Take,
col2Take,
col3Take;
switch(remainder)
{
case 1:
col1Take = take + 1;
col2Take = take;
col3Take = take;
break;
case 2:
col1Take = take + 1;
col2Take = take + 1;
col3Take = take;
break;
default:
col1Take = take;
col2Take = take;
col3Take = take;
break;
}
col1Items = items.Take(col1Take);
col2Items = items.Skip(col1Take).Take(col2Take);
col3Items = items.Skip(col1Take + col2Take).Take(col3Take);
Ultimately I am using these in a mvc Razor view
<div class="widgetColumn">
#Html.DisplayFor(m => col1Items, "MenuColumn")
</div>
<div class="widgetColumn">
#Html.DisplayFor(m => col2Items, "MenuColumn")
</div>
<div class="widgetColumn">
#Html.DisplayFor(m => col3Items, "MenuColumn")
</div>
In my first attempt I want to get rid of the colNItems and colNTake variables but i can't figure out the correct algorithm to make it work the same.
for (int i = 1; i <= 3; i++ )
{
IEnumerable<JToken> widgets = new List<JToken>();
var col = i;
switch(col)
{
case 1:
break;
case 2:
break;
case 3:
break;
}
}
Are the columns fixed-width? If so, then there's no need to do anything special with your collection. Just rely on the browser to do it for you. Have an outer container that has the overall width of the 3 columns, then just fill it with a div for each item (and float left). Set your inner containers to have a width exactly 1/3 of the outer container.
Here's a quick fiddle
Here's a quick hint at the style
div#outer{
width:300px;
}
div#outer > div{
width:100px;
float:left;
}
You could generalize:
int cols = 3;
IEnumerable<JToken> colItems[3]; // you can make this dynamic of course
int rem = numItems % cols;
int len = numItems / cols;
for (int col=0; col<cols; col++){
int colTake = len;
if (col < rem) colTake++;
colItems[col] = items.Skip(col*len).Take(colTake);
}
Haven't tested, but this should work for any number of columns.
Also whenever you need variables col1, col2, col3 think of col[0], col[1], col[2].
Can't you just do something like?
int len = numItems / 3;
int rem = numItems % 3;
int col1Take = len + (rem > 0 ? 1 : 0);
int col2Take = len + (rem > 1 ? 1 : 0);
int col3Take = len;
Edit:
A more generic solution that works for any number of columns (COLUMNS) would be:
int len = numItems / COLUMNS;
int rem = numItems % COLUMNS;
foreach (var i in Enumerable.Range(0, COLUMNS)) {
colTake[i] = len + (rem > i ? 1 : 0);
}
So you want the first n/3 items in the first column, next n/3 items in the 2nd column, etc.
var concreteList = items.ToList();
var count = concreteList.Count;
var take1 = count/3 + (count % 3 > 0 ? 1 : 0);
var take2 = count/3 + (count % 3 > 1 ? 1 : 0);
var col1 = concreteList.Take(take1);
var col2 = concreteList.Skip(take1).Take(take2);
var col3 = concreteList.Skip(take1 + take2);
I make a concrete list in order to avoid iterating the Enumerable multiple times. For example, if you had:
items = File.ReadLines("foo.txt");
Then you wouldn't be able to iterate it multiple times.
If you want to fill the columns round-robin you can use:
int numColumns = 3;
var result = Enumerable.Range(1,numColumns).Select(c =>
items.Where((x,ix) => ix % numColumns == c-1).ToArray()
);
This isn't fast, but it'll do the trick:
var col1Items = items.Select((obj, index) => new { Value = obj, Index = index })
.Where(o => o.Index % 3 == 0).Select(o => o.Value);
var col2Items = items.Select((obj, index) => new { Value = obj, Index = index })
.Where(o => o.Index % 3 == 1).Select(o => o.Value);
var col3Items = items.Select((obj, index) => new { Value = obj, Index = index })
.Where(o => o.Index % 3 == 2).Select(o => o.Value);
It uses the version of Select that includes an index parameter. You could use a GroupBy to speed this up a bit at the cost of a few lines of code.
If you want to go across then down see answer below this one, if you want to go down then across you can do it like this (use this code with the test below to see it working instead of the var result line there.:
var curCol = 0;
var iPer = items.Count() / 3;
var iLeft = items.Count() % 3;
var result = items.Aggregate(
// object that will hold items
new {
cols = new List<ItemElement>[3] { new List<ItemElement>(),
new List<ItemElement>(),
new List<ItemElement>(), },
},
(o, n) => {
o.cols[curCol].Add(n);
if (o.cols[curCol].Count() > iPer + (iLeft > (curCol+1) ? 1:0))
curCol++;
return new {
cols = o.cols
};
});
You can do this with aggregate. It would look like this:
void Main()
{
List<ItemElement> items = new List<ItemElement>() {
new ItemElement() { aField = 1 },
new ItemElement() { aField = 2 },
new ItemElement() { aField = 3 },
new ItemElement() { aField = 4 },
new ItemElement() { aField = 5 },
new ItemElement() { aField = 6 },
new ItemElement() { aField = 7 },
new ItemElement() { aField = 8 },
new ItemElement() { aField = 9 }
};
var result =
items.Aggregate(
// object that will hold items
new {
cols = new List<ItemElement>[3] { new List<ItemElement>(),
new List<ItemElement>(),
new List<ItemElement>(), },
next = 0 },
// aggregate
(o, n) => {
o.cols[o.next].Add(n);
return new {
cols = o.cols,
next = (o.next + 1) % 3
};
});
result.Dump();
}
public class ItemElement
{
public int aField { get; set; }
}
You end up with an object with an array of 3 lists (one for each column).
This example will run as is in linqPad. I recomment linqPad for these kind of POC tests. (linqPad.com)
it might help
IEnumerable<object> items = new Object[]{ "1", "2", "3", "4", "5", "6", "7","8", "9", "10", "11", "12","13", "14" };
IEnumerable<object> col1Items = new List<object>(),
col2Items = new List<object>(),
col3Items = new List<object>();
Object[] list = new Object[]{col1Items, col2Items, col3Items};
int limit = items.Count()/3;
int len = items.Count();
int col;
for (int i = 0; i < items.Count(); i++ )
{
if (len == 3) col = i;
else col = i / limit;
if (col >= 3) col = i%limit ;
((IList<object>)(list[col])).Add( items.ElementAt(i));
}
LinqLib (nuget: LinqExtLibrary) has an overload of ToArray() that does it:
using System.Collections.Generic;
using System.Linq;
using LinqLib.Array;
...
public void TakeEm(IEnumerable<int> data)
{
var dataAry = data as int[] ?? data.ToArray();
var rows = (dataAry.Length/3) + 1;
//var columns = Enumerable.Empty<int>().ToArray(3, rows);
// vvv These two lines are the ones that re-arrange your array
var columns = dataAry.ToArray(3, rows);
var menus = columns.Slice();
}