0

I've an object that is include property ID with values between 101 and 199. How to order it like 199,101,102 ... 198?

In result I want to put last item to first.


Rails import from csv to model

I have a csv file with dump data of table and I would like to import it directly into my database using rails.

I am currently having this code:

csv_text = File.read("public/csv_fetch/#{model.table_name}.csv")
ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{model.table_name}")
puts "\nUpdating table #{model.table_name}"
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
  row = row.to_hash.with_indifferent_access
  ActiveRecord::Base.record_timestamps = false
  model.create!(row.to_hash.symbolize_keys)
end

with help from here..

Consider my Sample csv:

id,code,created_at,updated_at,hashcode
10,00001,2012-04-12 06:07:26,2012-04-12 06:07:26,
2,00002,0000-00-00 00:00:00,0000-00-00 00:00:00,temphashcode
13,00007,0000-00-00 00:00:00,0000-00-00 00:00:00,temphashcode
43,00011,0000-00-00 00:00:00,0000-00-00 00:00:00,temphashcode
5,00012,0000-00-00 00:00:00,0000-00-00 00:00:00,temphashcode

But problem with this code is :

  • It is generating `id' as autoincrement 1,2,3,.. instead of what in csv file.
  • The timestamps for records where there is 0000-00-00 00:00:00 defaults to null automatically and throws error as the column created_at cannot be null...

Is there any way I can do it in generic way to import from csv to models? or would i have to write custom code for each model to manipulate the attributes in each row manually??

4

7 回答 7

7

所需的顺序没有意义(一些推理会有所帮助),但这应该可以解决问题:

int maxID = items.Max(x => x.ID); // If you want the Last item instead of the one
                                  // with the greatest ID, you can use
                                  // items.Last().ID instead.
var strangelyOrderedItems = items
    .OrderBy(x => x.ID == maxID ? 0 : 1)
    .ThenBy(x => x.ID);
于 2012-04-12T10:47:40.790 回答
1

取决于您是对列表中最大的项目感兴趣,还是对列表中的最后一个项目感兴趣:

internal sealed class Object : IComparable<Object>
{
   private readonly int mID; 
   public int ID { get { return mID; } }
   public Object(int pID) { mID = pID; }

   public static implicit operator int(Object pObject) { return pObject.mID; }
   public static implicit operator Object(int pInt) { return new Object(pInt); }

   public int CompareTo(Object pOther) { return mID - pOther.mID; }
   public override string ToString() { return string.Format("{0}", mID); }
}


List<Object> myList = new List<Object> { 1, 2, 6, 5, 4, 3 };

// the last item first
List<Object> last = new List<Object> { myList.Last() };
List<Object> lastFirst = 
   last.Concat(myList.Except(last).OrderBy(x => x)).ToList();

lastFirst.ForEach(Console.Write);
Console.WriteLine();
// outputs: 312456     

// or

// the largest item first
List<Object> max = new List<Object> { myList.Max() };
List<Object> maxFirst = 
   max.Concat(myList.Except(max).OrderBy(x => x)).ToList();

maxFirst.ForEach(Console.Write);
Console.WriteLine();
// outputs: 612345
于 2012-04-12T11:14:24.530 回答
0

怎么样

var orderedItems = items.OrderBy(x => x.Id)
var orderedItemsLastFirst = 
    orderedItems.Reverse().Take(1).Concat(orderedItems.Skip(1));

这将多次迭代列表,因此可能会更有效但不会使用太多代码。

如果更快的速度很重要,您可以编写一个专门的 IEnumerable 扩展,允许您在不转换为中间 IEnumerable 的情况下进行排序和返回。

于 2012-04-12T11:00:21.813 回答
0

结果我想把最后一项放在第一位

首先对列表进行排序

List<int> values = new List<int>{100, 56, 89..}; 
var result = values.OrderBy(x=>x);

添加用于交换元素的扩展方法List<T>

static void Swap<T>(this List<T> list, int index1, int index2)
{
     T temp = list[index1];
     list[index1] = list[index2];
     list[index2] = temp;
}

使用后

result .Swap(0, result.Count -1);
于 2012-04-12T10:48:33.910 回答
0

编辑:错过了关于您首先想要最后一项的部分。你可以这样做:

var objectList = new List<DataObject>();
var lastob = objectList.Last();
objectList.Remove(lastob);
var newList = new List<DataObject>();
newList.Add(lastob);
newList.AddRange(objectList.OrderBy(o => o.Id).ToList());

如果您正在谈论正常排序,您可以使用 linq 的 order by 方法,如下所示:
objectList = objectList.OrderBy(ob => ob.ID).ToList();

于 2012-04-12T10:45:15.757 回答
0

您可以使用单个 Linq 语句来实现这一点。

var ordering = testData
    .OrderByDescending(t => t.Id)
    .Take(1)
    .Union(testData.OrderBy(t => t.Id).Take(testData.Count() - 1));

以相反的方向排序并取前 1 个,然后以“正确的方式”排序并取除最后一个以外的所有内容并将它们合并在一起。这种方法有很多变体,但上述方法应该有效。

这种方法也适用于任意列表,无需知道最大数量。

于 2012-04-12T10:51:44.500 回答
-3
var myList = new List<MyObject>();
//initialize the list
var ordered = myList.OrderBy(c => c.Id); //or use OrderByDescending if you want reverse order
于 2012-04-12T10:49:09.493 回答